2017-03-03 107 views
0

考慮這個例子:使用類屬性陣營渲染()

class App extends Component { 
    constructor() { 
    super(); 
    this.person = new Person("Tim", 23); 

    this.state = { 
     name: this.person.name 
    } 
    } 

    changeName() { 
    this.person.setName("Jane"); 
    this.person.setAge(22); 
    setState({name: this.person.name}); 
    } 

    render() { 
    return (
     <div> 
     <div>Your name is: {this.state.name}</div> 
     <div>Your age is: {this.person.age}</div> 
     <div><button onClick={this.changeName.bind(this)}>Change Name</button></div> 
     </div> 
    ) 
    } 
} 

什麼我查詢這裏是當一個變量應該被添加到狀態。在這個例子中,雖然這個工作年齡不在狀態。

我在處理對象時遇到了很多問題,我不確定將任何呈現的對象屬性添加到狀態是否是最佳做法,或者如果我只是應該擔心如何將屬性添加到狀態可能會被更新。我很確定我在這個例子中做什麼會很糟糕,因爲年齡正在更新,但沒有反映在狀態中。

關於「正確」執行此操作的任何想法?

+0

爲什麼不乾脆讓國家的'person'一部分? – bejado

+0

@bejado,我可以,是這樣做的正確方法嗎?然後我會調用this.state.person.setName()嗎?在狀態中有方法似乎是錯誤的,並且對象可能存在對象屬性更新的情況,但未調用setState()。 – user11406

+0

我會讓'person'成爲不可變的對象。每次您需要更改姓名或年齡時,請創建一個包含更改的新人。然後'setState({person:newPerson})' – bejado

回答

0

很簡單。正確的方法是使用狀態來顯示您想要顯示的屬性。

在這種情況下,你的代碼應該是

setState({ 
    name: this.person.name, 
    age: this.person.age 
}); 

爲什麼?那麼,這是最好的做法,並鼓勵在文檔中使用this.state。在組件上附加屬性(this)通常適用於方法。

此外,請考慮組件方法shouldComponentUpdate(nextProps, nextState),componentWillUpdate(nextProps, nextState),componentDidUpdate(prevProps, prevState)。 很明顯,如果你需要他們的論點,你將無法檢索你改變的舊/新屬性,如果他們不在stateprops

0

React並不指示您如何管理數據。如果您使用的getter/setter方法的對象,那麼它可能是簡單的對整個對象存儲在狀態:

changeName() { 
    this.person.setName("Jane"); 
    this.person.setAge(22); 

    this.setState({person: this.person}); 
    } 

通過這種方式,你的對象仍然是負責數據,和任何內部處理這意味着,而結果對象本身存儲在組件狀態。

也就是說,使用像Person這樣的數據對象,雖然可能,但不是慣用的React。我會推薦使用類似Redux的東西,並設置單向數據流。這意味着創建一個Reducer來管理你的狀態,並使用動作創建者與Redux商店進行通信。

您可以在reducer中初始化對象的默認值。這是從Redux商店默認返回的。

您的Reducer會偵聽UPDATE_PERSON操作,該操作會爲整個更新的Person對象帶來有效負載。這將如下保存在狀態:

減速器/ person.js

const UPDATE_PERSON = 'UPDATE_PERSON'; 

const initialState = { 
    name: "Tim", 
    age: 23 
} 

const personReducer(state = initialState, action) { 
    switch (action.type) { 
     case UPDATE_PERSON: 
      return { 
       ...state, 
       name: action.payload.name, 
       age: action.payload.name 
      } 
     default: 
      return state; 
    } 
} 

你行動的創建者是一個簡單的功能與type財產和某種有效載荷:

(據推測)行動/人。JS

export const updatePerson(data) { 
    return { 
     type: UPDATE_PERSON, 
     payload: data 
    } 
} 

你那麼終極版商店連接到您的組件,並用行動創造者的行動派遣到商店:

import { connect } from 'react-redux'; 
import * as PersonActionCreators from '../actions/person'; 

class App extends Component { 

    changeName() { 
     this.props.updatePerson({name: "Jane", age: 22}); 
    } 

    render() { 
    return (
     <div> 
     <div>Your name is: {this.props.person.name}</div> 
     <div>Your age is: {this.props.person.age}</div> 
     <div><button onClick={this.changeName.bind(this)}>Change Name</button></div> 
     </div> 
    ) 
    } 

} 

const mapStateToProps = (state) => ({ 
    person: state.person 
}); 

const mapDispatchToProps = { 
    updatePerson: PersonActionCreators.updatePerson 
}; 

export default connect(mapStateToProps, mapDispatchToProps)(App); 

上面的代碼假設你在有一個根減速以下格式:

import { combineReducers } from 'redux'; 
import personReducer from './reducers/person'; 

const appReducer = combineReducers({ 
    person: personReducer 
}) 

const rootReducer = (state, action) => appReducer(state, action); 
export default rootReducer; 

您將需要創建存儲並將其連接到您的根減速器。詳情可以在here找到。

combineReducers功能只是幫助構建根減速器:

的combineReducers輔助功能將一個對象,其值是 不同減少功能集成在單一減小功能可以 通行證createStore。

這是更多的樣板,但它是在React中處理應用程序狀態的既定和最流行的方式。看起來好像很多東西都是在開始的時候,但是一旦你熟悉了reducer,行動創造者和連接功能,它變得非常簡單。

Redux使用uni-directional data-flow,這意味着數據流從頂層組件向下到子組件。有狀態的組件保持在最低限度;但是在需要狀態的地方,connect函數提供了它。當組件需要修改狀態時,它通過動作創建者來完成。 reducer監聽動作並相應地更新狀態。關於這一主題

見丹·阿布拉莫夫的自由理論家課程的精彩介紹終極版: