【问题标题】:How do I ensure axios call sets the state in useEffect?如何确保 axios 调用在 useEffect 中设置状态?
【发布时间】:2021-05-17 18:19:45
【问题描述】:

我正在尝试使用 axios 获取一些数据。 我有这样的物品状态:

const [subGroup, setSubGroup] = useState([])
const [items, setItems] = useContext(ItemsContext)

然后我使用这个项目状态,过滤一些项目,将它们存储在另一个数组状态中,然后渲染它们。

const getSubGroups = () => {
    console.log(items) // still empty array
    
        const [group] = items.filter(item => (
            item.name === match.params.group ? item.subgroups : null
        ))
        const subgroups = group.subgroups

        setSubGroup(subgroups)
    

}

useEffects(我只有第二个,但现在我想在刷新时更新项目的状态,所以这就是为什么有两个):

useEffect(async () => {
    await axios.get('http://localhost:3001/Items')
        .then(res => setItems(res.data));
    console.log(items)
    getSubGroups()
    }, [])
useEffect(() => {
    getSubGroups()
},[match.params.group])

控制台日志返回一个空数组,我收到 'Cannot read property 'subgroups' of undefined 的错误。我尝试使用没有 async 和 await 关键字的方法。结果相同。如何确保 useEffect 获取数据然后继续渲染项目?任何帮助,将不胜感激。 注意:res.data 返回我正确需要的数组。

编辑:

如果我想访问更多嵌套数据怎么办?我看了你的例子,它恰好适用于这种情况,但如果是这种情况怎么办?我尝试遵循逻辑,但没有输出:

const [items, setItems] = useContext(ItemsContext)
//each item has nested array data
const data = useMemo(() => {
    const [subWithData] = items.filter(item => (
        item.name === match.params.group ? item.subgroups : null
    )).filter(item => (
        item.subgroups.map(sub => (
            sub.name === match.params.subGroup
        ))
    ))
    return subWithData?.data?? []


}, [match.params.group, match.params.subGroup, items])

我在哪里做错了?对不起,如果这个问题太蹩脚,但我是新人。

【问题讨论】:

  • 好吧,不是真的,太多建议,大部分都试过了。只是糊涂了。当我需要它时,状态仍然不会改变。
  • 写下这个:useEffect(() => {console.log(items)}, [items]) ,让我们知道它打印了什么。
  • 相同的结果,空数组。
  • 我解决了这个问题。我在 jsx 渲染返回语句中使用过滤器/映射链传输了 getSubGroups() 函数,它现在按预期工作。我只是不知道在 return 语句中移动这么多逻辑是否是一个好习惯。

标签: reactjs axios use-effect


【解决方案1】:

您可以使用useMemo 钩子来记忆结果,而不是在源/依赖项没有更改时重新计算:

const [items, setItems] = useContext(ItemsContext)

const subGroups = useMemo(() => {
  const [group] = items.filter(item => (
    item.name === match.params.group
  ))
  return group?.subgroups ?? []
}, [match.params.group, items])

useEffect(() => {
  axios.get('http://localhost:3001/Items')
    .then((res) => setItems(res.data))
}, [])

return <>
  <div>{  ... you can use subGroups here  ... }</div>
</>

【讨论】:

  • @rollstapewz 我看到了你的编辑。你为什么要链接你的filter,即使用它两次?您可以在 1 个过滤器中进行所有过滤。从技术上讲,它(你在编辑部分写的)应该可以工作。如果它不起作用,其原因可能是 datafilter 即您应用了错误的过滤器,因此它返回 []。因此,解决问题的最佳方法是创建一个沙盒来重现此问题。
猜你喜欢
  • 2021-08-30
  • 2021-09-26
  • 2021-03-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 2019-11-01
  • 2021-02-11
  • 2021-10-17
相关资源
最近更新 更多