为什么添加额外的状态有助于更新其他状态?

Why adding extra state helps to update other state?

完整代码如下:

import * as React from 'react';
import { View, ScrollView, StyleSheet } from 'react-native';
import {
  Appbar,
  Searchbar,
  List,
  BottomNavigation,
  Text,
  Button,
} from 'react-native-paper';

const AccordionCollection = ({ data }) => {
  var bookLists = data.map(function (item) {
    var items = [];
    for (let i = 0; i < item.total; i++) {
      items.push(
        <Button mode="contained" style={{ margin: 10 }}>
          {i}
        </Button>
      );
    }
    return (
      <List.Accordion
        title={item.title}
        left={(props) => <List.Icon {...props} icon="alpha-g-circle" />}>
        <View
          style={{
            flexDirection: 'row',
            flexWrap: 'wrap',
            alignItems: 'flex-start',
            backgroundColor: 'white',
          }}>
          {items}
        </View>
      </List.Accordion>
    );
  });
  return bookLists;
};

const MusicRoute = () => {
  const DATA = [
    {
      key: 1,
      title: 'Zain dishes',
      total: 21,
    },
    {
      key: 2,
      title: 'Sides',
      total: 32,
    },
    {
      key: 3,
      title: 'Drinks',
      total: 53,
    },
    {
      key: 4,
      title: 'Aesserts',
      total: 14,
    },
  ];
  const [data, setData] = React.useState(DATA);
  const [searchQuery, setSearchQuery] = React.useState('');
  const [sortAZ, setSortAZ] = React.useState(false);

  const onChangeSearch = (query) => {
    setSearchQuery(query);
    const newData = DATA.filter((item) => {
      return item.title.toLowerCase().includes(query.toLowerCase());
    });
    setData(newData);
  };

  const goSortAZ = () => {
    setSortAZ(true);
    setData(
      data.sort((a, b) => (a.title > b.title ? 1 : b.title > a.title ? -1 : 0))
    );
  };

  const goUnSort = () => {
    setSortAZ(false);
    setData(DATA);
  };
  return (
    <View>
      <Appbar.Header style={styles.appBar}>
        <Appbar.BackAction onPress={() => null} />

        <Searchbar
          placeholder="Search"
          onChangeText={onChangeSearch}
          value={searchQuery}
          style={styles.searchBar}
        />

        <Appbar.Action
          icon="sort-alphabetical-ascending"
          onPress={() => goSortAZ()}
        />
        <Appbar.Action icon="library-shelves" onPress={() => goUnSort()} />
      </Appbar.Header>
      <ScrollView>
        <List.Section title="Accordions">
          <AccordionCollection data={data} />
        </List.Section>
      </ScrollView>
    </View>
  );
};

const AlbumsRoute = () => <Text>Albums</Text>;

const MyComponent = () => {
  const [index, setIndex] = React.useState(0);
  const [routes] = React.useState([
    { key: 'music', title: 'Music', icon: 'queue-music' },
    { key: 'albums', title: 'Albums', icon: 'album' },
  ]);

  const renderScene = BottomNavigation.SceneMap({
    music: MusicRoute,
    albums: AlbumsRoute,
  });

  return (
    <BottomNavigation
      navigationState={{ index, routes }}
      onIndexChange={setIndex}
      renderScene={renderScene}
    />
  );
};

const styles = StyleSheet.create({
  appBar: {
    justifyContent: 'space-between',
  },
  searchBar: {
    width: '60%',
    shadowOpacity: 0,
    borderRadius: 10,
    backgroundColor: '#e4e3e3',
  },
});

export default MyComponent;

Expo Snack Link

有两个奇怪的机制。

第一

如果我删除 goSortAZ() 中的 sortAZ(true)goUnSort() 中的 sortAZ(false),状态 data 在您按下 (1) 排序后停止更新(2) 取消按钮排序超过 3 次。

第二

如果我删除组件外的 DATA 数组,排序和取消排序按钮不会 work/update。

如果我不删除这两个,我可以对列表进行排序和取消排序。 虽然实现了功能,但是感觉代码比较乱

我的问题是:

完全删除 sortAZ 变量(不需要使用它,除非你想拥有 loading 状态,但因为你没有发出 http 请求,所以没有必要)并替换 goSortAZ 与以下内容:

记得克隆原始数组以创建一个新副本,然后对该副本进行排序。 这工作正常。

  const goSortAZ = () => {
    setData(
      [...data].sort((a, b) => (a.title > b.title ? 1 : b.title > a.title ? -1 : 0))
    );
  };

我建议对 unSort 方法也使用相同的技术。