React setState 不更新组件
React setState doesnt update the component
我不知道为什么我的 React 应用程序在我刷新状态后不会更新。
我正在显示 table,其中可以通过单击突出显示行。
在触摸屏上向下滑动时,它应该会重新加载。动画正在显示,但 table 未更新且突出显示保持不变。
我提供了一个小代码示例。如果此 post 需要更多代码或信息,请随时发表评论。
提前致谢。
const dummyKonten = [
{ id: 1,
icon: 'a',
name: 'Sparkasse',
isSelect: false },
{ id: 3,
icon: 'b',
name: 'Volksbank',
isSelect: false }]
constructor(props) {
super(props);
this.state = {
isLoading: true,
isRefreshing: false,
konten: [...dummyKonten],
updatedKonten: [...dummyKonten],
};
}
onRefresh = () => {
const reset = [...this.state.konten];
this.setState(
{
isRefreshing: true,
}
);
wait(2000).then(() => {
this.setState(
{ isRefreshing: false,
updatedKonten: reset } )}
);
}
selectItem = (item) => {
item.isSelect = !item.isSelect;
const index = this.state.updatedKonten.findIndex(
indexItem => indexItem.id === item.id
);
const newKonten = [...this.state.updatedKonten];
newKonten[index] = item;
this.setState(
{
updatedKonten: newKonten,
}
);
};
render(){
return(
<SafeAreaView style={styles.view}>
<StatusBar barStyle="dark-content" />
<View style={styles.viewBody}>
<FlatList
data={this.state.updatedKonten}
extraData={this.state.updatedKonten}
renderItem={this.renderKonto}
ItemSeparatorComponent={this.flatListItemSeparator}
refreshControl={
<RefreshControl colors={["#5797C5"]} refreshing={this.state.isRefreshing} onRefresh={this.onRefresh} />}
showsHorizontalScrollIndicator={false}
keyExtractor={item => item.id.toString()}
/>
</View>
<HomeButton navigation={this.props.navigation} />
</SafeAreaView>
);
}
好的,我知道了。
问题是我在该州克隆数组的方式。
对于此问题,需要对数组进行 深度复制 。
所以我改变了
constructor(props) {
super(props);
this.state = {
isLoading: true,
isRefreshing: false,
konten: [...dummyKonten],
updatedKonten: [...dummyKonten],
};
}
至:
constructor(props) {
super(props);
this.state = {
isLoading: true,
isRefreshing: false,
konten: JSON.parse(JSON.stringify(dummyKonten)),
updatedKonten: JSON.parse(JSON.stringify(dummyKonten)),
};
}
啊,我想我明白现在可能发生的事情了。你真的不应该需要使用JSON到serialize/deserialize你的数据来克隆它。您应该避免在生产代码中使用这种模式。
我认为问题是您的 selectItem
处理程序中的状态突变。如果我的猜测是正确的,selectItem
回调可能被您的项目渲染器 this.renderKonto
.
使用
我怀疑您正在传递对 state.updatedKonten
状态数组中 item
元素的引用,对其进行变异,然后将其保存回数组中。问题在于,即使 state.updatedKonten
是一个新的数组引用,state.updatedKonten[index]
处的项目也是之前的旧 item
对象引用。
selectItem = (item) => {
item.isSelect = !item.isSelect; // <-- (1) item mutation
const index = this.state.updatedKonten.findIndex(
indexItem => indexItem.id === item.id
);
const newKonten = [...this.state.updatedKonten];
newKonten[index] = item; // <-- (2)
this.setState({
updatedKonten: newKonten,
});
};
因此 React 可能会放弃重新渲染项目,因为它们的对象引用没有改变。
解决方案
基本上更新 selectItem
处理程序以使用功能状态更新和浅拷贝状态以及正在更新的任何嵌套状态。您可以将前一个状态映射到下一个状态数组,并且当项目 id 匹配时,浅复制 item
并更新 isSelect
属性.
selectItem = (item) => {
this.setState((prevState) => ({
updatedKonten: prevState.updatedKonten.map((itemEl) =>
itemEl.id === item.id
? {
...itemEl,
isSelect: !itemEl.isSelect
}
: itemEl
)
}));
};
我不知道为什么我的 React 应用程序在我刷新状态后不会更新。 我正在显示 table,其中可以通过单击突出显示行。 在触摸屏上向下滑动时,它应该会重新加载。动画正在显示,但 table 未更新且突出显示保持不变。
我提供了一个小代码示例。如果此 post 需要更多代码或信息,请随时发表评论。
提前致谢。
const dummyKonten = [
{ id: 1,
icon: 'a',
name: 'Sparkasse',
isSelect: false },
{ id: 3,
icon: 'b',
name: 'Volksbank',
isSelect: false }]
constructor(props) {
super(props);
this.state = {
isLoading: true,
isRefreshing: false,
konten: [...dummyKonten],
updatedKonten: [...dummyKonten],
};
}
onRefresh = () => {
const reset = [...this.state.konten];
this.setState(
{
isRefreshing: true,
}
);
wait(2000).then(() => {
this.setState(
{ isRefreshing: false,
updatedKonten: reset } )}
);
}
selectItem = (item) => {
item.isSelect = !item.isSelect;
const index = this.state.updatedKonten.findIndex(
indexItem => indexItem.id === item.id
);
const newKonten = [...this.state.updatedKonten];
newKonten[index] = item;
this.setState(
{
updatedKonten: newKonten,
}
);
};
render(){
return(
<SafeAreaView style={styles.view}>
<StatusBar barStyle="dark-content" />
<View style={styles.viewBody}>
<FlatList
data={this.state.updatedKonten}
extraData={this.state.updatedKonten}
renderItem={this.renderKonto}
ItemSeparatorComponent={this.flatListItemSeparator}
refreshControl={
<RefreshControl colors={["#5797C5"]} refreshing={this.state.isRefreshing} onRefresh={this.onRefresh} />}
showsHorizontalScrollIndicator={false}
keyExtractor={item => item.id.toString()}
/>
</View>
<HomeButton navigation={this.props.navigation} />
</SafeAreaView>
);
}
好的,我知道了。
问题是我在该州克隆数组的方式。 对于此问题,需要对数组进行 深度复制 。 所以我改变了
constructor(props) {
super(props);
this.state = {
isLoading: true,
isRefreshing: false,
konten: [...dummyKonten],
updatedKonten: [...dummyKonten],
};
}
至:
constructor(props) {
super(props);
this.state = {
isLoading: true,
isRefreshing: false,
konten: JSON.parse(JSON.stringify(dummyKonten)),
updatedKonten: JSON.parse(JSON.stringify(dummyKonten)),
};
}
啊,我想我明白现在可能发生的事情了。你真的不应该需要使用JSON到serialize/deserialize你的数据来克隆它。您应该避免在生产代码中使用这种模式。
我认为问题是您的 selectItem
处理程序中的状态突变。如果我的猜测是正确的,selectItem
回调可能被您的项目渲染器 this.renderKonto
.
我怀疑您正在传递对 state.updatedKonten
状态数组中 item
元素的引用,对其进行变异,然后将其保存回数组中。问题在于,即使 state.updatedKonten
是一个新的数组引用,state.updatedKonten[index]
处的项目也是之前的旧 item
对象引用。
selectItem = (item) => {
item.isSelect = !item.isSelect; // <-- (1) item mutation
const index = this.state.updatedKonten.findIndex(
indexItem => indexItem.id === item.id
);
const newKonten = [...this.state.updatedKonten];
newKonten[index] = item; // <-- (2)
this.setState({
updatedKonten: newKonten,
});
};
因此 React 可能会放弃重新渲染项目,因为它们的对象引用没有改变。
解决方案
基本上更新 selectItem
处理程序以使用功能状态更新和浅拷贝状态以及正在更新的任何嵌套状态。您可以将前一个状态映射到下一个状态数组,并且当项目 id 匹配时,浅复制 item
并更新 isSelect
属性.
selectItem = (item) => {
this.setState((prevState) => ({
updatedKonten: prevState.updatedKonten.map((itemEl) =>
itemEl.id === item.id
? {
...itemEl,
isSelect: !itemEl.isSelect
}
: itemEl
)
}));
};