React setState 不更新组件

时间:2021-02-25 09:43:06

标签: reactjs react-native react-native-flatlist

我不知道为什么我的 React 应用在刷新状态后不会更新。 我正在显示一个表格,其中的行可以通过单击突出显示。 当在触摸屏上向下滑动时,它应该重新加载。动画正在显示,但表格没有更新并且突出显示保持不变。

我提供了一个小代码示例。如果这篇文章需要更多代码或信息,请随时发表评论。

提前致谢。

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

2 个答案:

答案 0 :(得分:0)

好的,我知道了。

问题是我在该州克隆数组的方式。 对于这个问题,需要对数组进行深度复制。 所以我改变了

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

答案 1 :(得分:0)

啊,我想我知道现在可能会发生什么。你真的不应该需要使用 JSON 来序列化/反序列化你的数据来克隆它。你应该避免在你的生产代码中使用这种模式。

我认为问题在于您的 selectItem 处理程序中的状态突变。如果我的猜测是正确的,selectItem 回调可能被您的项目渲染器 this.renderKonto 使用。

我怀疑您正在传递对 item 状态数组中的 state.updatedKonten 元素的引用,对其进行变异,然后将其保存回数组中。问题在于,即使 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
    )
  }));
};