React Hooks:无法分配给只读属性

IT技术 reactjs typescript react-hooks
2021-05-02 12:50:29

我正在尝试更新用 React.createElement() 创建的对象。我要更新的属性是particleCopy.props.style.top. 下面是我的代码。

import React, { useState } from 'react';
import './Particles.scss';

export default function Particles() {
  const particleStyle = { color: 'blue', position: 'absolute', top: '0px' };
  const [particle, setParticle] = useState(
    React.createElement('div', { style: particleStyle }, '*')
  );

  const moveParticleDown = (particle, top) => {
    const particleCopy = Object.assign({}, particle);
    particleCopy.props.style.top = top + 'px';
    setParticle(particleCopy);
  };

  return (
    <div className="particles_container">
      <div className="particles">{particle}</div>
      <div className="controls">
        <button onClick={() => moveParticleDown(particle, 10)}>down</button>
      </div>
    </div>
  );
}

我收到以下错误

Uncaught TypeError: Cannot assign to read only property 'top' of object '#<Object>'

2个回答

您的particleCopy函数只是创建 的浅表副本particle,这意味着您正在尝试改变particle指向的对象您可以查看一个深度克隆库,或者,现在在 React 中看起来更惯用的方法是,尽可能地将对象向下传播:

const particleCopy = {
  ...particle,
  props: {
    ...particle.props,
    style: {
      ...particle.props.style,
      top: top + 'px'
    }
  }
}
setParticle(particleCopy);

如果您应该在状态中添加元素,我实际上在互联网上搜索是否值得推荐。我不认为这是你应该在 React 中实现这种行为的方式。好吧,如果它有效,我会保持开放的态度。发现另一个解决此讨论的问题(检查第二条评论):将元素添加到状态react

更不用说做副本了,可能会很昂贵。

为什么不将位置保存为状态?

export default function Particles() {
  const particleStyle = { color: 'blue', position: 'absolute', top: '0px' };
  // if ever you need to track other than top
  const [position, setPosition] = useState({top: 0, bottom: 0, left: 0, right: 0});

  const moveParticleDown = p => {
    setPosition({top: p});
  };

  return (
    <div className="particles_container">
      <div className="particles">
        <div style={...particleStyle, top: `${position.top}px`} /> 
      </div>
      <div className="controls">
        <button onClick={() => moveParticleDown(10)}>down</button>
      </div>
    </div>
  );
}