考虑这个例子:
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;的任何想法这样做的方法?
答案 0 :(得分:0)
这很简单。正确的方法是对要显示的属性使用状态。
在这种情况下,您的代码应为
setState({
name: this.person.name,
age: this.person.age
});
为什么呢?嗯,这是最佳做法,在文档中鼓励使用this.state
。在组件(this
)上附加属性通常用于方法。
另外,请考虑组件方法shouldComponentUpdate(nextProps, nextState)
,componentWillUpdate(nextProps, nextState),
componentDidUpdate(prevProps, prevState)
。
显然,如果您需要他们的参数,您将无法检索您更改的旧/新属性,如果它们不在state
或props
上。
答案 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课程: