2017-03-03 106 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监听动作并相应地更新状态。关于这一主题

见丹·阿布拉莫夫的自由理论家课程的精彩介绍终极版: