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

时间:2016-08-25 21:26:53

标签: javascript reactjs

我有一个React应用程序,其中父组件的道具传递给子组件,然后道具设置子项的状态。

将更新后的值发送到父组件后,子组件不会使用更新的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>
    }
}

4 个答案:

答案 0 :(得分:53)

您需要在您的孩子中实施componentWillReceiveProps

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

修改 componentWillReceiveProps现已弃用,将被删除,但上述文档链接中还有其他建议。

答案 1 :(得分:6)

componentWillReceiveProps中呼叫setState()并不会导致额外的重新渲染。接收道具是一个渲染,如果在componentDidUpdate之类的方法中执行,则this.setState将是另一个渲染。我建议您在shouldComponentUpdate中执行this.state.name !== nextProps.name,以便始终检查是否有任何更新。

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

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

答案 2 :(得分:3)

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

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

答案 3 :(得分:1)

几件事。至少可以说,单击时绑定功能的方式并不常见。我建议您要么在构造函数上执行此操作,要么改用箭头函数(这会将函数自动绑定到类)。

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>
    );
  }
}

此外,我建议您决定是否需要从父级或子级中管理/更新道具。如果父级负责处理状态,则应将handleUpdate传播给父级:

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

您不需要使用其他任何功能(在React 16+中)来管理从子级到父级的道具,反之亦然。

通常,这些“双向”案例是结构“气味”,表示每个组件的关注点分离已被错误调整或尚未完全弄清。