Rya*_*yan 3 reactjs react-native redux react-redux
我正在尝试使用 react native 设置 redux,但是当商店更新时它没有更新我的组件。
class Dinner extends React.Component {
componentDidUpdate() {
console.log('does not get called when store update');
}
setSelected = (meal) => {
var index = this.props.selectedDinner.indexOf(meal);
if (index === -1) {
console.log('Adding meal to selected: '+meal.name);
if (this.props.selectedDinner[0] === null) {
var tempArr = this.props.selectedDinner;
tempArr[0] = meal;
this.props.setSelectedDinner(tempArr);
} else if(this.props.selectedDinner[1] === null) {
var tempArr = this.props.selectedDinner;
tempArr[1] = meal;
this.props.setSelectedDinner(tempArr);
} else if(this.props.selectedDinner[2] === null) {
var tempArr = this.props.selectedDinner;
tempArr[2] = meal;
this.props.setSelectedDinner(tempArr);
}
} else {
console.log("removing meal from selected: "+meal.name)
var tempArr = this.props.selectedDinner;
tempArr[index] = null;
this.props.setSelectedDinner(tempArr);
}
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.forceUpdate()
};
render() {
return (
<View style={{flex: 1, width: 360, justifyContent: 'center', alignItems: 'center', paddingBottom: 20}}>
<View style={{width: 340, backgroundColor: 'white', justifyContent: 'flex-start', alignItems: 'center'}}>
<Text style={{height: 50, fontSize: 20, fontWeight: 'bold', flex: 1, justifyContent: 'center', alignItems: 'center'}}>Dinner</Text>
{
this.props.dinnerFeed.map((prop, key) =>
prop === null ?
<TouchableOpacity style={{width: 320, height: 120, backgroundColor: 'lightgrey', flex: 1, justifyContent: 'center', alignItems: 'center', zIndex: 1, marginBottom: 10, flexShrink: 0}} key={key}><LoadingMealTile /></TouchableOpacity>
:
(prop === 'none' ?
<TouchableOpacity style={{width: 320, height: 120, backgroundColor: 'lightgrey', flex: 1, justifyContent: 'center', alignItems: 'center', zIndex: 1, marginBottom: 10, flexShrink: 0}} key={key}><BlankMealTile /></TouchableOpacity>
:
this.props.selectedDinner === null || this.props.selectedDinner.indexOf(prop) === null ?
<TouchableOpacity onPress={this.setSelected.bind(this, prop)} style={{width: 320, height: 120, backgroundColor: 'lightgrey', flex: 1, justifyContent: 'center', alignItems: 'center', zIndex: 1, marginBottom: 10, flexShrink: 0}} key={key}><MealTile selected={-1} name={prop.name} id={prop.id} url={prop.url} key={key}/></TouchableOpacity>
:
<TouchableOpacity onPress={this.setSelected.bind(this, prop)} style={{width: 320, height: 120, backgroundColor: 'lightgrey', flex: 1, justifyContent: 'center', alignItems: 'center', zIndex: 1, marginBottom: 10, flexShrink: 0}} key={key}><MealTile selected={this.props.selectedDinner.indexOf(prop)} name={prop.name} id={prop.id} url={prop.url} key={key}/></TouchableOpacity>
)
)
}
<TouchableOpacity onPress={this.props.loadFeedMeals} style={{width: 320, height: 50, backgroundColor: 'lightgrey', flex: 1, justifyContent: 'center', alignItems: 'center', zIndex: 1, marginBottom: 10}}><Text style={{fontSize: 15, }}>Load More Meals</Text></TouchableOpacity>
</View>
</View>
);
}
}
function mapStateToProps(state) {
return {
dinnerFeed: state.dinnerFeed,
selectedDinner: state.selectedDinner,
}
};
function mapDispatchToProps(dispatch) {
return {
setDinnerMeals: (dinnerMeals) => dispatch(setDinnerMeals(dinnerMeals)),
setSelectedDinner: (selectedDinner) => dispatch(setSelectedDinner(selectedDinner)),
}
};
export default connect(mapStateToProps, mapDispatchToProps)(Dinner);
Run Code Online (Sandbox Code Playgroud)
函数 setSelectedDinner 正确更改了 redux 存储,但组件没有调用其 componentDidUpdate 函数
编辑:这是减速器代码
export default (state, action) => {
console.log(action);
switch (action.type) {
case "SET-SELECTED-DINNER":
return {
...state,
selectedDinner: action.selectedDinner
};
default:
return state;
}
};
Run Code Online (Sandbox Code Playgroud)
我相信这段代码不应该直接改变状态,因为我在 reactjs 项目中使用了这个 reducer 来实现 redux
Redux 状态被更新但连接组件没有更新的最常见原因是在 reducer 中改变状态。一个非常相似的常见问题是无法识别 Redux connect HoC 执行浅比较。
这是因为 Redux 通过使用对象相等来检查更改。(如果===比较返回 true,则认为该对象未更改。)
考虑以下不正确的减速器:
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return state.visibilityFilter = action.filter;
default:
return state
}
}
Run Code Online (Sandbox Code Playgroud)
由于上面的 reducer 改变了状态,所以不会触发更新。
一个正确的例子(取自Redux 文档)如下所示:
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
}
Run Code Online (Sandbox Code Playgroud)
除了上述不改变状态而是始终为任何更改的新状态返回新状态的最佳实践之外,重要的是要记住 Redux connect 对mapStateToProps.
考虑您的mapStateToProps函数的简化版本:
function mapStateToProps(state) {
return {
selectedDinner: state.selectedDinner,
}
};
Run Code Online (Sandbox Code Playgroud)
现在考虑您如何将选定的晚餐传递给您的setSelectedDinner行动(再次简化):
setSelected = (meal) => {
var index = this.props.selectedDinner.indexOf(meal);
// when index === -1 we need to add this meal
if (index === -1) {
// there is no meal at index 0 so we add it
if (this.props.selectedDinner[0] === null) {
// NOTICE - the line below still references selected dinner in state!
var tempArr = this.props.selectedDinner;
tempArr[0] = meal;
// NOTICE - we are calling setSelectedDinner with the same object
// that comes from state!
this.props.setSelectedDinner(tempArr);
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,在你的 reducer 函数中,你很容易用它自己替换 selectedDinner 对象,所以 Redux 看不到更新。
解决您的问题的最快更改是修改 reducer 函数以读取(切片调用会克隆您的数组):
export default (state, action) => {
switch (action.type) {
case "SET-SELECTED-DINNER":
return {
...state,
selectedDinner: action.selectedDinner.slice()
};
default:
return state;
}
};
Run Code Online (Sandbox Code Playgroud)
还有许多其他小的更改可以使此代码更易于使用并且不易出现此类错误。两个简单的是:
将修改 selectedDinner 数组的逻辑移出组件,并将其放置在 reducer 中。
介绍选择器
| 归档时间: |
|
| 查看次数: |
5331 次 |
| 最近记录: |