在React render()中使用类属性

时间:2017-03-03 21:05:20

标签: reactjs

考虑这个例子:

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

我在这里查询的是应该将变量添加到状态。在这个例子中,虽然这个工作年龄不在该州。

我在使用对象时遇到了很多问题,我不确定将任何渲染对象属性添加到状态是否是最佳做法,或者我是否应该只担心向属性添加属性说明他们是否可能会更新。我很确定我在这个例子中所做的事情会变坏,因为年龄正在升级,但是没有反映在这个州。

关于&#34;正确&#34;的任何想法这样做的方法?

2 个答案:

答案 0 :(得分:0)

这很简单。正确的方法是对要显示的属性使用状态。

在这种情况下,您的代码应为

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

为什么呢?嗯,这是最佳做法,在文档中鼓励使用this.state。在组件(this)上附加属性通常用于方法。

另外,请考虑组件方法shouldComponentUpdate(nextProps, nextState)componentWillUpdate(nextProps, nextState), componentDidUpdate(prevProps, prevState)。 显然,如果您需要他们的参数,您将无法检索您更改的旧/新属性,如果它们不在stateprops上。

答案 1 :(得分: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属性和某种有效负载:

(大概) actions / person.js

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

然后将Redux商店连接到您的组件,并使用操作创建者将操作分派给商店:

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

上面的代码假设您有一个root reducer,格式如下:

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,这意味着数据流从顶级组件向下传递到子组件。有状态的组件保持在最低限度;但是在需要state的地方,connect函数提供它。当组件需要修改状态时,它通过动作创建者来完成。 Reducer会听取操作并相应地更新状态。

有关Redux的精彩介绍,请参阅Dan Abramov关于此主题的免费egghead课程: