在React子组件上使用props更新状态

Updating state with props on React child component

本文关键字:props 更新 状态 React 组件      更新时间:2023-09-26

我有一个React应用,其中父组件中的props被传递给子组件,然后这些props设置了子组件的状态。

当我把更新后的值发送给父组件后,子组件不会用更新后的props来更新状态。

我如何让它更新子组件的状态?

我的简化代码:

class Parent extends React.Component {
    constructor (props) {
        super(props);
        this.state = {name: ''} 
    }
    componentDidMount () {
        this.setState({name: this.props.data.name});
    }
    handleUpdate (updatedName) {
        this.setState({name: updatedName});
    }
    render () {
        return <Child name={this.state.name} onUpdate={this.handleUpdate.bind(this)} />
    }
}

class Child extends React.Component {
    constructor (props) {
        super(props);
        this.state = {name: ''} 
    }
    componentDidMount () {
        this.setState({name: this.props.name});
    }
    handleChange (e) {
        this.setState({[e.target.name]: e.target.value});
    }
    handleUpdate () {
        // ajax call that updates database with updated name and then on success calls onUpdate(updatedName)
    }
    render () {
        console.log(this.props.name); // after update, this logs the updated name
        console.log(this.state.name); // after update, this logs the initial name until I refresh the brower
        return <div>    
                    {this.state.name}
                    <input type="text" name="name" value={this.state.name} onChange={this.handleChange} />
                    <input type="button" value="Update Name" onClick={this.handleUpdate.bind(this)} />
                </div>
    }
}

您需要在您的孩子中实现componentWillReceiveProps:

componentWillReceiveProps(newProps) {
    this.setState({name: newProps.name});
}

编辑: componentWillReceiveProps现在已弃用并将被删除,但在上面的文档链接中有其他建议

在componentWillReceiveProps中调用setState()不会导致额外的重新渲染。接收道具是一个渲染和这个。如果setState在componentDidUpdate这样的方法中执行,它将是另一个渲染。我建议在shouldComponentUpdate中执行this.state.name !== nextProps.name,以便始终检查任何更新。

componentWillReceiveProps(nextProps) {
    this.setState({name: nextProps.name});
}
shouldComponentUpdate(nextProps) {
    return this.state.name !== nextProps.name;
}

最好检查一下是否需要更新状态,因为这会导致重新渲染。

componentWillReceiveProps(newProps) {
  if (this.state.name !== newProps.name) {
    this.setState({name: newProps.name});
  }
}

有几件事。至少可以这么说,在click上绑定函数的方式是不寻常的。我建议你要么在构造函数中这样做,要么使用箭头函数(这会自动将函数绑定到类)。

export default class Parent extends Component {
    constructor (props) {
        super(props);
        this.state = {name: ''} 
    }
    handleUpdate = (updatedName) => {
        this.setState({name: updatedName})
    }
    render () {
        return <Child name={this.state.name} onUpdate={this} />
    }
}
export default class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: "" };
  }
  componentDidMount() {
    this.setState({ name: this.props.name });
  }
  handleChange = (e) => {
    this.setState({ name: e.target.value });
  }
  handleUpdate() {
    // ajax call that updates database with updated name and then on success calls onUpdate(updatedName)
  }
  render() {
    console.log(this.props.name); // after update, this logs the updated name
    console.log(this.state.name); // after update, this logs the initial name until I refresh the brower
    return (
      <div>
        {this.state.name}
        <input
          type="text"
          name="name"
          value={this.state.name}
          onChange={this.handleChange}
        />
        <input
          type="button"
          value="Update Name"
          onClick={this.handleUpdate}
        />
      </div>
    );
  }
}

此外,我建议您决定是否需要从Parent或Child管理/更新props 。如果Parent负责处理状态,那么你应该将handleUpdate传播给Parent:

//@Parent component
<Child handleUpdate={()=> this.handleUpdate} .../>
//@Child component
handleUpdate = () => {
   this.props.handleUpdate
}

你不应该被要求使用任何其他函数(在React 16+中)来管理从子到父的道具,反之亦然。

通常这些"双向"的情况是结构的"气味",表明每个组件的关注点分离已经被错误地调整或者还没有完全弄清楚。