使用 Object.assign() 时 React 组件不重置状态?

use*_*295 0 javascript object reactjs

我有一个 React 组件,它似乎没有正确重置其初始状态。我正在使用 Object.assign() 来确保传递的道具具有所有字段(以改进可能未定义键的旧数据库条目)。

newProfile 是一个完整的配置文件(带有标题字段),而 legacyProfile 是添加标题字段之前的条目。为什么/如何传递 legacyProfile 的组件以某种方式保留来自另一个实例的一些数据(传递 newProfile 的组件),以及如何防止这种情况发生以确保我总是从一个新的 profileInitialState 开始?

const profileInitialState = {
  name: '',
  title: '',
  headline: '',
  bio: ''
}

class Bio extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      editingProfile: Object.assign(profileInitialState, this.props.profile)
    }
  }
  
  render() {
    const { profile } = this.props;
    const { editingProfile } = this.state;
    
    console.log(profile); // props profile has correct info
    console.log(editingProfile); // state profile takes on old values
    
    return (
      <div>
        <h1>{editingProfile.name}</h1>
        <h2>{editingProfile.title}</h2>
        <h3>{editingProfile.headline}</h3>
        <p>{editingProfile.bio}</p>
      </div>
    );
  }
}

const newProfile = {
  name: 'Test 1',
  title: 'Title 1',
  headline: 'Headline 1',
  bio: 'Bio 1'
}

const legacyProfile = {
  name: 'Test 2',
  title: 'Title 2',
  bio: 'Bio 2'
}

ReactDOM.render(
  <React.Fragment>
  <Bio profile={newProfile} />
  <Bio profile={legacyProfile} />
  </React.Fragment>,
  document.getElementById('root')
);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root">
    <!-- This element's contents will be replaced with your component. -->
</div>
Run Code Online (Sandbox Code Playgroud)

Cer*_*nce 5

Object.assign将从第 2 个及以上的所有参数中分配自己的可枚举属性到第一个参数中的对象中。所以

editingProfile: Object.assign(profileInitialState, this.props.profile)
Run Code Online (Sandbox Code Playgroud)

变异 profileInitialState

那条线类似于

for (const [key, val] of Object.entries(this.props.profile)) {
  profileInitialState[key] = val;
}
Run Code Online (Sandbox Code Playgroud)

因此,该行第二次运行时,第一次的结果可能仍存在于 中profileInitialState

相反,使用

editingProfile: Object.assign({}, profileInitialState, this.props.profile)
Run Code Online (Sandbox Code Playgroud)

创建一个全新的对象:

editingProfile: Object.assign(profileInitialState, this.props.profile)
Run Code Online (Sandbox Code Playgroud)
for (const [key, val] of Object.entries(this.props.profile)) {
  profileInitialState[key] = val;
}
Run Code Online (Sandbox Code Playgroud)

或者,更简洁地说:

editingProfile: { ...profileInitialState, ...this.props.profile }
Run Code Online (Sandbox Code Playgroud)