【问题标题】:React Native rerendering UI after using array.map使用 array.map 后 React Native 重新渲染 UI
【发布时间】:2021-10-02 17:15:48
【问题描述】:

我试图让图标在单击时切换其视觉效果(如复选框)。通常在本机反应中我会做这样的事情:

const [checkbox, setCheckbox] = React.useState(false);
...
<TouchableHighlight underlayColor="transparent" onPress={() => {setCheckbox(!setCheckbox)}}> 
    {added ? <MaterialIcons  name="playlist-add-check" size={40} />
    : <MaterialIcons  name="playlist-add" size={40} />}
</TouchableHighlight>

但是我做了一些更改,现在我似乎无法复制这种行为。我正在使用 AsyncStorage 类来存储和获取要显示的对象数组。为简单起见,在下面的示例中我删除了存储代码,并且每个对象都有一个 'id' 和一个 'added' 属性,这本质上是复选框的布尔值。

我现在正在尝试更新每次按下时向用户显示的图标。我知道正在调用该函数,但它不会更新图标。我正在使用 array.map 创建图标列表。我这里做了一个demo,代码如下:https://snack.expo.dev/@figbar/array-map-icon-update

const templateObject = {
  id: 0,
  added: false,
};
const templateObject2 = {
  id: 1,
  added: true,
};
export default function App() {
  const [savedNumbers, setSavedNumbers] = React.useState([]);

  React.useEffect(() => {
    setSavedNumbers([templateObject,templateObject2]);
  }, []);

  const populateSavedNumbers = () =>
    savedNumbers.map((num, index) => <View key={index}>{renderPanel(num.id,num.added)}</View>);
  const updateNumber = (id) => {
    let capturedIndex = -1;
    for(var i = 0; i < savedNumbers.length; i += 1) {
        if(savedNumbers[i].id === id) {
          capturedIndex = i;
          break;
        }
    }
    let _tempArray = savedNumbers;
    _tempArray[capturedIndex].added = !_tempArray[capturedIndex].added;
    setSavedNumbers(_tempArray);
  }
  const renderPanel = (id:number, added:boolean) => {
    return (
        <View>
          <TouchableHighlight underlayColor="transparent" onPress={() => {updateNumber(id);}}> 
              {added ? <MaterialIcons  name="playlist-add-check" size={40} />
              : <MaterialIcons  name="playlist-add" size={40} />}
           </TouchableHighlight>
        </View>
    );
  }
  return (
    <View>
    <View>buttons:</View>
      <View>{populateSavedNumbers()}</View>
    </View>
  );
}

【问题讨论】:

    标签: reactjs react-native user-interface render


    【解决方案1】:

    这是一个常见的 React 陷阱,当看起来应该重新渲染时,事情不会重新渲染。 React 在新旧状态之间进行浅层比较,以决定是否触发重新渲染。这意味着,当声明一个变量等于一个对象或数组的状态变量时,不会触发重新渲染,因为这两个变量现在引用相同的底层数据结构。

    在这种情况下,您将 _tempArray 设置为引用数组 savedNumbers 而不是创建新数组。因此,React 的浅比较返回为“相等”,并且它认为没有必要重新渲染。

    要解决此问题,请更改此行:

    let _tempArray = savedNumbers;
    

    到这里:

    let _tempArray = [...savedNumbers];
    

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 1970-01-01
      • 2019-09-26
      • 2018-12-27
      • 1970-01-01
      • 2022-08-12
      • 2021-11-14
      • 2019-07-19
      • 1970-01-01
      相关资源
      最近更新 更多