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

boo*_*oom 49 javascript reactjs

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

谢谢你的帮助.

Mik*_*ver 81

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

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

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

  • 就像你可以将`onChange`回调或类似的东西传递给React内置子项,如`<input />`.你也为自己的孩子做同样的事.让孩子接受`onTouch`(或任何你想称之为)的属性,并让孩子在孩子的触摸事件处理程序中执行`this.props.onTouch`.父进程应设置`onTouch = {this.childTouchHandler}`或类似的东西来处理这个问题.所以父母应该总是处理它自己的状态,但是它可以对"自定义"事件做出反应并处理它发送给孩子们的回调. (3认同)

sup*_*ary 15

回答为什么的问题

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

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

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

如果组件可以改变其props,我们将更改父节点可访问的对象,即使在父节点已经渲染之后也是如此.这可能会导致各种奇怪的行为,例如,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'))
);
Run Code Online (Sandbox Code Playgroud)

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

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

修改道具将是双向绑定

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

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

  • 我喜欢你的解释,谢谢! (2认同)

Val*_*éry 13

在React中,stateprops提供不同的目标:state允许组件维护一些不断变化的值,同时props是将这些值传播给子级的机制.

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


Gal*_*ger 9

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

<Parent>
  <Child name={ this.state.childName } />
</Parent>
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)

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