状态列表更改不会导致重新渲染 Next.js/React

时间:2021-06-12 07:42:26

标签: javascript reactjs next.js

我有以下状态:

const [places, setPlaces] = useState(false)
const [selectedPlaces, setSelectedPlaces] = useState([])

我通过调用一个 API 异步填充地点,该 API 返回一个类似于以下内容的对象数组:

[
    {name: "Shop #1", id: 1},
    {name: "Shop #2", id: 2}
]

我的目标是渲染这些对象,并在 selectedPlaces 状态中添加/删除它们的 ID。

渲染:

return (
  <div>
    <div>
      You have selected {selectedPlaces.length} total places
    </div>
    (places === false)
      ? <div>Loading...</div>
      : places.map(place => { // render places from the places state when loaded
          let [name, id] = [place.name, place.id]
          return <div onClick={() => {
            setSelectedPlaces(selected => {
              selected.push("dummy data to simplify")
              return selected
            })
          }}>{name}</div>
        })

  </div>
)

我已经移除了钥匙并添加了虚拟数据以使动作更简单。

<块引用>

单击 div 时出现问题,直到我使用快速刷新或通过其他方法(使用浏览器/NextJS)强制重新渲染之前,“您已选择...总位置”不会刷新.这是正确的行为吗?好像状态没有改变,但 console.log 上的 setSelectedPlaces 显示新数据,表示它正在改变。

我试过了:

  • useEffect 状态创建 selectedPlaces 处理程序,该处理程序将使用所选位置的长度 setAmtPlaces。同样的问题也出现了。
  • 搜索/通读多个帖子/GitHub 问题,例如 thisthis
  • 以前我遇到过这个问题,用真/假替换列表状态,但我不能对这个问题使用这种方法,因为它是动态加载的数据量。

1 个答案:

答案 0 :(得分:2)

  • 为三元运算符添加一个 {} 包装器:

    {
        places === false 
         ? (...)
         : (....)
    }
    
  • push 改变状态。在 concat

    中使用传播或 setSelectedPlaces
    setSelectedPlaces(selected => 
      selected.concat("abc")
    )
    
  • let [name, id] = [place.name, place.id] 可以更改为 let { name, id } = place

这是一个片段:

const { useState } = React;

function App() {
  const [places, setPlaces] = useState([
      { name: "Shop #1", id: 1 },
      { name: "Shop #2", id: 2 }
  ])
  const [selectedPlaces, setSelectedPlaces] = useState([])
  
  const onPlaceClick = id => setSelectedPlaces(state => state.concat(id))
  
  return (
    <div>
      <div> You have selected {selectedPlaces.length} total places </div>
      { (places === false)
        ? <div>Loading...</div>
        : places.map(({ id, name }) => 
            <div onClick={_ => onPlaceClick(id)}>{name}</div>
          )
      }
      <span>{selectedPlaces.join()}</span>
    </div>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>