【问题标题】:React native useState hook not updating state with async call using axios in custom hook使用自定义钩子中的 axios 响应本机 useState 钩子不使用异步调用更新状态
【发布时间】:2024-05-19 02:20:02
【问题描述】:

我创建了一个自定义挂钩来对返回对象数组的 rest api 进行异步调用。我有两种异步方法。第一个方法返回一个对象列表。在成功的休息调用中,状态数组 [dataEntry] 得到更新,但在第二次调用时,发布请求返回单个对象。当我尝试将新返回的对象添加到状态数组 [dataEntry] 时,我无法看到添加到数组中的新对象。

import { useState, useContext } from 'react';
import restApi from '../api/restApi';
import { Context as AuthContext } from '../context/AuthContext';


export default () => {
    const { state } = useContext(AuthContext);
    const [lastPage, setLastPage] = useState(true);
    const [nextPageNumber, setNextPageNumber] = useState(0);
    const [dataEntry, setDataEntry] = useState([]);
    const [errorMessage, setErrorMessage] = useState(null);
    const [dataUpdate, setDataUpdate] = useState(false);


    const getAllData = async (pageNumber, pageSize) => {
        try {
            restApi.get('/data/list', {
                headers: {
                    Authorization: 'Bearer ' + state.tokenData,
                    'Content-Type': 'application/json'
                }
            }).then(response => {
                console.log(response.data.result);
                setLastPage(response.data.lastPage);
                setNextPageNumber(response.data.nextPageNumber);
                setDataEntry([...response.data.result]);
                setDataUpdate(true);
            })


        } catch (error) {
            console.log(error.response.data);
        }
    }

    const createData = async ({ dataName }) => {
        try {
            console.log('creating data ' + dataName);
            restApi.post(
                "/data", {
                dataName
            }, {
                headers: {
                    Authorization: 'Bearer ' + state.tokenData,
                    'Content-Type': 'application/json'
                }
            }).then(response => {
                console.log(response.data);
                console.log(dataEntry.length)
                setDataEntry([...dataEntry, response.data]);
                console.log(dataEntry.length)
                setDataUpdate(true);
            })


        } catch (error) {
            console.log(error.response.data);
        }
    }



    return [getAllData, createData, dataEntry, lastPage, nextPageNumber, dataUpdate];


}

【问题讨论】:

    标签: react-native axios use-state


    【解决方案1】:

    由于您要根据之前的状态更新状态dataEntry,因此将回调函数传递给setDataEntry。还要确保传播prev状态并合并响应结果。

    getAllData 函数

    ...
    setDataEntry(prev => [...prev, ...response.data.result]);
    ...
    

    createData 函数

    ...
    setDataEntry(prev => [...prev, ...response.data]);
    ...
    

    另外,在createData 函数中,console.log(dataEntry.length) 不会打印最新结果,因为状态更新是异步的。

    【讨论】:

    • 我确实尝试过提供回调函数,但它仍然没有更新。同样在 createData 函数中,帖子返回单个对象而不是数组。下面是代码的样子setDataEntry(prev => [...prev, response.data]);。但是,如果我只是用返回的对象更新状态,则状态值会更新为例如:setDataEntry([response.data]); 擦除数组并向其中添加一个元素。有点困惑为什么向数组中添加元素不起作用。
    • 状态更新是异步的,因此您将无法更新状态并立即打印状态...您如何调用这些函数(createData 和 getAllData)?
    • import React, { useEffect, useState } from 'react'; const Data = () => { //custom hook const [getData, createData] = useData(); const [dataName, setDataName] = useState(''); useEffect(() => {getData(0, 10); }, []) const addData = () => {createData({ dataName }); } return ( <View> <Input onChangeText={setDataName} keyboardType='default' /> <Button title="Add" onPress={addData} /> </View> ) } export default Data;