簡體   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