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

为什么我们都有stateprops? 为什么我们不只有一个数据源? 我想更新组件的props,并使其重新呈现其自身及其所有子代。 看起来很简单,但我不知道如何让组件更新其自身或父项的道具。

谢谢你的帮助。

boom asked 2020-02-12T04:07:27Z
6个解决方案
80 votes

React的哲学是道具应该是不变的并且自上而下的。 这意味着父母可以将喜欢的任何道具值发送给孩子,但孩子不能修改自己的道具。 您要做的是对传入的道具做出反应,然后根据需要修改孩子的状态。

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

如果您想让某个子动作发生在子状态上,而该子动作会修改状态中的某些内容,那么您要做的就是将回调传递给该子动作,该子动作可以在给定的动作上执行。 然后,此回调可以修改父级的状态,从而可以在重新渲染时向子级发送不同的道具。

Mike Driver answered 2020-02-12T04:08:28Z
15 votes

回答为什么的问题

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

这意味着当我们调用user.name时,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'))
);

我们渲染应用程序。 它将“ Hermione”输出到Shadow DOM。 我们渲染配置文件,它输出“ Voldemort”。 该应用程序现在是错误的。 应该说“ Voldemort”,因为user.name是“ Voldemort”,但是我们已经输出了“ Hermione”,并且更改它为时已晚。

该值在应用程序的不同部分将有所不同。

修改道具将是双向绑定

突变道具将是双向绑定的一种形式。 我们将修改树上方其他组件可能依赖的值。

Angular 1有了这个,您可以随时随地更改任何数据。 为了工作,它需要周期性的$ digest。 基本上,它会四处循环,重新渲染DOM,直到所有数据完成传播为止。 这就是Angular 1这么慢的部分原因。

superluminary answered 2020-02-12T04:09:33Z
13 votes

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

不允许孩子自己更改通过props获得的值,因为React设计人员发现维护这种方式构建的应用程序更容易。 他们的观点是,当只允许一个组件更新某些状态时,更容易发现更改它的人,并找到错误的根源。

Valéry answered 2020-02-12T04:09:59Z
9 votes

组件本身会更改其状态,并且不会更改其自身的状态,而是会更改儿童的道具。

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

父母可以更改自己的状态并更改孩子的名字,但这会更改其孩子的道具。

编辑1:为了从子对象向其父对象调用事件,您应该在子对象中传递一个事件处理程序,如下所示:

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

在此代码中,当您单击“子级”按钮时,它将把事件传递给其父级。传递事件的目的是使组件分离。 也许在您的应用程序中您需要执行此特定操作,但是在另一个应用程序中,您将有不同的用法。

Gal Schlezinger answered 2020-02-12T04:10:33Z
0 votes

我的解决方案截然不同,但有些人可能会遇到它。 在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>
    );
}

我添加了一个render方法,它解决了我能够传递props的问题:

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

希望这对某人有帮助。

Lewis answered 2020-02-12T04:11:02Z
-21 votes

与这里提供的答案相反,如果您不介意反对“ React way”这个古怪的怪癖,实际上您可以直接更新道具。 在React.js中,找到以下代码行:

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

并把它们注释掉。 瞧,可变道具!

joeyp answered 2020-02-12T04:11:27Z
translate from https://stackoverflow.com:/questions/26089532/why-cant-i-update-props-in-react-js