简体   繁体   English

我在反应本机应用程序中更新 useState 后,网格中的项目没有更新

[英]Items in grid are not updating after I update the useState in react native applcation

I have a react native project.我有一个反应原生项目。 Part of my react native project is a grid that I created.我的 react native 项目的一部分是我创建的网格。 When a user clicks on an item in the grid, I want to update an array that I have set in state const [selectedHomeTypes, setSelectedHomeTypes] = useState(['Houses']) .当用户单击网格中的项目时,我想更新我在 state const [selectedHomeTypes, setSelectedHomeTypes] = useState(['Houses'])中设置的数组。

When I add an item to the array, I want it to udpate the grid so that all the items in the array have a blue background.当我向数组中添加一个项目时,我希望它更新网格,以便数组中的所有项目都具有蓝色背景。 If there was 1 item in selectedHomeTypes then 1 item in the grid has a blue background.如果selectedHomeTypes中有 1 项,则网格中的 1 项具有蓝色背景。 If I add a second item to selectedHomeTypes , I want two items in the grid to have a blue background and sale with when I unselect an item that is deleted from the array.如果我向selectedHomeTypes添加第二个项目,我希望网格中的两个项目具有蓝色背景并在我取消选择从数组中删除的项目时出售。

What is hapening now is that selectedHomeTypes is being updated like normal so when an item that is not in the state is clicked on it is added to the array and same with unslelect.现在正在发生的事情是selectedHomeTypes正在像往常一样更新,因此当单击不在 state 中的项目时,它将被添加到数组中,并且与 unslelect 相同。 The issue is that the background colors of the items are not updating at all and no matter what happens, only the default item has blue background.问题是项目的背景 colors 根本没有更新,无论发生什么,只有默认项目有蓝色背景。 Nothing is visually changing....视觉上没有任何变化......

Main Screen:主屏幕:

const [selectedHomeTypes, setSelectedHomeTypes] = useState(['Houses'])
const updateSelectedHomeTypes = (selected) => {
  let selectedHome = selectedHomeTypes
  if(selectedHome.length == 0){
    setSelectedHomeTypes(['Houses'])
  }
  if(selectedHome.includes(selected)){
    let target = selectedHome.indexOf(selected)
    selectedHome.splice(target, 1)
    if(selectedHome.length == 0){
      setSelectedHomeTypes(['Houses'])
    } else {
      setSelectedHomeTypes(selectedHome)
    }
  } else {
    selectedHome.push(selected)
    setSelectedHomeTypes(selectedHome)
  }
}

  return (
    <View style={styles.filterContainer}>
      <ScrollView style={styles.scrollContainer}>
        <View style={styles.header}>
          <Text style={styles.label}>
            Filter
          </Text>
          <TouchableOpacity onPress={() => {resetFilter()}}>
            <Text style={[styles.label, styles.blueText]}>
              Reset
            </Text>
          </TouchableOpacity>
        </View>
        <View style={styles.sectionContainer}>
          <FlatList 
            style={styles.homeTypeContainer}
            data={homeTypeOptions1}
            keyExtractor={(item) => item.key}
            numColumns={numberOfColumns}
            renderItem={(item) => {
              return(               
                <GridItemComponent 
                  item={item} 
                  updateSelectedHomeTypes={updateSelectedHomeTypes}
                  selectedHomeTypes={selectedHomeTypes}
                />
              )}}
          />
        </View>
      </ScrollView>
      <TouchableOpacity onPress={() => {applyFilters()}}>
        <View style={styles.buttonContainer}>
          <Text style={styles.buttonText}>Apply Filters</Text>
        </View>
      </TouchableOpacity>
    </View>
  )

gridItemComponenet:网格项目组件:

const GridItemComponent = (props) => {
  const {
    item,
    updateSelectedHomeTypes,
    selectedHomeTypes
  } = props

  return(
    <>
      {
        selectedHomeTypes.includes(item.item.value) ? <TouchableOpacity  style={styles.itemContainerBlue} onPress={() => {updateSelectedHomeTypes(item.item.value)}}>
                                                        <View style={styles.item}>
                                                          <Image style={styles.icon} source={item.item.image}/>
                                                          <Text style={styles.label}>{item.item.value}</Text>
                                                        </View>
                                                      </TouchableOpacity>
                                                    : <TouchableOpacity  style={styles.itemContainer} onPress={() => {updateSelectedHomeTypes(item.item.value)}}>
                                                        <View style={styles.item}>
                                                          <Image style={styles.icon} source={item.item.image}/>
                                                          <Text style={styles.label}>{item.item.value}</Text>
                                                        </View>
                                                      </TouchableOpacity>
          }
    </>
  )
}

list of property type options:属性类型选项列表:

const numberOfColumns = 3

const homeTypeOptions1 = [
  {
    key: 1,
    value: 'Houses',
    image: require('./src/assets/home.png')
  },
  {
    key: 2,
    value: 'Condos',
    image: require('./src/assets/building.png')
  },
  {
    key: 3,
    value: 'Lot/Land',
    image: require('./src/assets/management.png')
  },
  {
    key: 4,
    value: 'Multi-family',
    image: require('./src/assets/multi-family.png')
  },
  {
    key: 5,
    value: 'Manufactured',
    image: require('.//src/assets/tiny-house.png')
  },
  {
    key: 6,
    value: 'Townhomes',
    image: require('.//src/assets/townhouse.png')
  }
]

as you can see in the image below, the selectedHomeTypes has 3 items in the array but only 1 item is highlighted.如下图所示, selectedHomeTypes在数组中有 3 个项目,但只有 1 个项目被突出显示。 I am having trouble trying to update the background color of selected items dynamically我在尝试动态更新所选项目的背景颜色时遇到问题

已选择 3 项,但 1 项具有蓝色背景

At a glance I think this is the problem:乍一看,我认为这是问题所在:

When you do this:当你这样做时:

selectedHome.push(selected)
setSelectedHomeTypes(selectedHome)

React doesn't re-render because you're setting selectedHomeTypes to the same array that's already in state. React 不会重新渲染,因为您将selectedHomeTypes设置为已经在 state 中的相同数组。

You've pushed a new entry into it but React is doing an identity comparison between the old state and the new state to decide whether a rerender is needed.您已将新条目推入其中,但 React 正在旧 state 和新 state 之间进行身份比较,以确定是否需要重新渲染。 In this case newArray === oldArray so it doesn't trigger an update.在这种情况下newArray === oldArray所以它不会触发更新。

You could dodge this by spreading into a new array (and appending the new item instead of calling push):您可以通过传播到一个新数组(并附加新项目而不是调用 push)来避免这种情况:

setSelectedHomeTypes([...selectedHome, selected])

When updating state using its previous value, use the callback argument (to avoid stale state values).使用之前的值更新 state 时,请使用回调参数(以避免过时的 state 值)。

https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

It should be它应该是

this.setState(state=>
    ({selectedHomeTypes: state.selectedHomeTypes.concat(selected)})
);

If you are updating a state property, using another state property, it's best to use class components.如果要更新 state 属性,使用另一个 state 属性,最好使用 class 组件。

State updates to arrays should be done using methods that return a new array ( push does not while concat does). State 对 arrays 的更新应该使用返回一个新数组的方法来完成( push不会,而concat会)。

See this comprehensive article to learn how to update state arrays in React.请参阅这篇综合文章以了解如何在 React 中更新 state arrays。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM