繁体   English   中英

为什么我不能在react.js中更新道具?

[英]Why can't I update props in react.js?

为什么我们同时拥有stateprops 为什么我们不只有一个数据源? 我想更新一个组件的props ,让它自己和它的所有孩子重新渲染。 看起来很简单,但我无法弄清楚如何让组件更新自己的或其父级的道具。

谢谢你的帮助。

React的理念是道具应该是不可变的和自上而下的。 这意味着父母可以将其喜欢的任何道具值发送给孩子,但孩子不能修改自己的道具。 你做的是对传入的道具作出反应然后,如果你愿意,根据传入的道具修改孩子的状态。

因此,您永远不会更新自己的道具或父母的道具。 永远。 您只需更新自己的状态,并对父级给出的道具值做出反应。

如果你想让一个动作发生在一个修改状态的东西上,那么你所做的就是将一个回调传递给它可以在给定动作上执行的子动作。 然后,此回调可以修改父级的状态,然后可以在重新渲染时向子级发送不同的道具。

回答为什么的问题

在React中,道具从父母到孩子向下流动。

这意味着当我们调用ReactDOM.render ,React可以呈现根节点,传递任何道具,然后忘记该节点。 完成了。 它已经渲染了。

这发生在每个组件上,我们渲染它,然后沿着树向下移动,深度优先。

如果组件可以改变其道具,我们将更改父节点可访问的对象,即使在父节点已经渲染之后也是如此。 这可能会导致各种奇怪的行为,例如, user.name可能在应用程序的一个部分中具有一个值,而在另一个部分中具有不同的值,并且它可能在下次触发渲染时自行更新。

举一个虚构的例子:

// App renders a user.name and a profile
const App = (props) => 
  React.createElement('div', null, [
    props.user.name,
    React.createElement(Profile, props)
  ])

// Profile changes the user.name and renders it
// Now App has the wrong DOM.
const Profile = ({user}) => {
  user.name = "Voldemort" // Uh oh!
  return React.createElement('div', null, user.name);
}

// Render the App and give it props
ReactDOM.render(
  React.createElement(App, {user: {name: "Hermione"}}), 
  document.getElementById('app'))
);

我们渲染app。 它将“Hermione”输出到Shadow DOM。 我们渲染个人资料,输出“Voldemort”。 该应用程序现在错了。 它应该说“Voldemort”,因为user.name是“Voldemort”,但是我们已经输出了“Hermione”,现在改变它已经太晚了。

应用程序的不同部分的值会有所不同。

修改道具将是双向绑定

变异道具将是双向绑定的一种形式。 我们将修改可能由树上方的另一个组件所依赖的值。

Angular 1有这个,你可以随时随地改变任何数据。 为了工作,它需要一个周期性的$摘要。 基本上,它会循环并重新渲染DOM,直到所有数据都完成传播。 这是Angular 1如此缓慢的部分原因。

在React中, stateprops服务于不同的目标: state允许组件维护一些变化的值,而props则是将这些值传播给孩子的机制。

儿童不能自己改变他们通过道具获得的价值,因为React设计师发现维护以这种方式构建的应用程序更容易。 他们的观点是,当只允许一个组件更新某个状态时,更容易发现谁更改了它,并找到了bug的根源。

组件本身改变了它的状态 ,并且改变了它自己的状态,而是改变了它们的道具

<Parent>
  <Child name={ this.state.childName } />
</Parent>

父可以更改自己的状态并更改子名称,但它会更改子项的道具。

edit1:用于调用从子进程到其父进程的事件,您应该向子进程传递一个事件处理程序,如下所示:

var Child = React.createClass({
  render: function() {
    return (<button onClick={ this.props.onClick }>Hey</button>);
  }
});

var Parent = React.createClass({
  onChildClick: console.log.bind(console), // will print the event..
  render: function() {
    return (<Child onClick={ this.onChildClick } />);
  }
});

React.renderComponent(<Parent />, document.body);

在此代码中,当您单击Child的按钮时,它会将事件传递给其父级。 传递事件的目的是解耦组件。 也许在你的应用程序中你需要这个特定的动作,但在你将拥有的另一个应用程序中,你将以不同的方式使用它。

我的解决方案相当不同,但有些人可能会碰到它。 在Chrome Dev工具上,它一直说我的道具是只读的,当我尝试将它们进一步传递时,我会收到错误。 现在,原因是因为我没有调用render()方法。 我是这样调用我的组件:

const Navigation = () =>{

    return (
        <div className="left-navigation">
            <ul>
                <Link to='/dashboard'><li>Home</li></Link>
                <Link to='/create-seedz'><li>Create Seedz</li></Link>
                <Link to='/create-promotion'><li>Create Promotion</li></Link>
                <Link to='/setting'><li>Setting</li></Link>
                <SignOutButton  />
            </ul>
        </div>
    );
}

我添加了一个渲染方法,它解决了我能够传递道具的问题:

class Navigation extends Component{
render(){
    return (
        <div className="left-navigation">
            <ul>
                <Link to='/dashboard'><li>Home</li></Link>
                <Link to='/create-seedz'><li>Create Seedz</li></Link>
                <Link to='/create-promotion'><li>Create Promotion</li></Link>
                <Link to='/setting'><li>Setting</li></Link>
                <SignOutButton user={this.props.user} signedOut={this.props.signedOut} authed={this.props.authed}/>
            </ul>
        </div>
    );
}
}

希望这有助于某人。

与这里提供的答案相反,你实际上可以直接更新道具,如果你不介意藐视迂腐的圈子“反应方式”。 在React.js中,找到以下代码行:

Object.freeze(element.props);
Object.freeze(element);

并评论出来。 瞧,可变的道具!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM