“void”类型的参数不可分配给“SetStateAction<never[]>”类型的参数

时间:2021-06-30 03:26:53

标签: javascript typescript react-native

我收到以下错误:

Argument of type 'void' is not assignable to parameter of type 'SetStateAction<never[]>'.

我的相关代码如下所示:

const ViewEvents: React.FC<ViewEventsProps> = ({ navigation }) => {

const flatListRef = useRef(null);
const [limit] = useState(5);
const [page, setPage] = useState(1);
const [clientData, setClientData] = useState([]);
const [serverData, serverDataLoaded] = useState([]);
const [pending_process, setPending_process] = useState(true);
const [loadmore, setLoadmore] = useState(false);
const [refresh, setRefresh] = useState(false);

const getEvents = async (thePage: any) => {
    try {
        const value = await AsyncStorage.getItem('user_id');
        if (value !== null) {
            // We have data!!
            const user_id = JSON.parse(value)
            const response = await APIKit.get('/v1/events/user-events/' + user_id)
                .then((response) => {
                    console.log(response.data)
                    return response.data.slice((thePage - 1) * limit, thePage * limit);
                }, (error) => {
                    console.log(error);
                });
        }
    } catch (error) {
        // Error retrieving data
    }
}

const requestToServer = async (thePage: any) => {
    let data = await getEvents(thePage);
    console.log('data', data);
    serverDataLoaded(data);
};

显然,数据没有使用从 getEvents 函数返回的数据进行初始化。我想不通的是为什么?我正在使用 TypeScript,到目前为止,getEvents 函数没有抛出任何错误。

我是 React 和 TypeScript 的新手,所以我可能会遗漏一些东西,到目前为止,我在网上看到的所有类似问题似乎都与我的错误无关。

2 个答案:

答案 0 :(得分:1)

首先让我们看看SetStateAction<never[]>。如果您将鼠标悬停在此行中的 serverData 上:

const [serverData, serverDataLoaded] = useState([]);

它会告诉您 serverData 的类型是 never[]。问题是 [] 没有足够的信息让打字稿知道应该放入该数组的内容,因为没有内容可以推断类型。为此,您需要将类型参数传递给 useState

我不知道您的数据的形状,但类似于:

const [serverData, serverDataLoaded] =
  useState<{ id: number, name: string }[]>([]);

现在,如果您将鼠标悬停在 serverData 上,您应该看到:

const serverData: {
    id: number;
    name: string;
}[]

如果您将鼠标悬停在 serverDataLoaded 上,您应该看到:

const serverDataLoaded: React.Dispatch<React.SetStateAction<{
    id: number;
    name: string;
}[]>>

所以现在该函数是一个 React 设置状态动作,它采用您定义的类型。


现在让我们看看问题的另一面:为什么要分配的值是 void?。

如果您将鼠标悬停在 getEvents 上,您应该会看到该函数的推断返回类型。你应该看到这个:

const getEvents: (thePage: any) => Promise<void>

因此打字稿认为该函数返回一个承诺,即解析为 void。这意味着打字稿在您的函数中没有看到 return 语句。

这是为什么?好吧,唯一的 return 语句是在嵌套函数中。您似乎混淆了 async/await 和基于 Promise 的 .then() 样式。你永远不应该使用两者。在这种情况下,您只需要 await 调用 api,然后使用它返回的任何内容:

const response = await APIKit.get('/v1/events/user-events/' + user_id)
console.log(response.data)
return response.data.slice((thePage - 1) * limit, thePage * limit);

现在 return 语句在正常函数流中命中,现在在嵌套函数中。

请参阅:How to return a result properly from async/await function? 了解更多信息。


现在,毕竟,getEvents 返回一个值而不是 void,并且 serverDataserverDataLoaded 都具有正确的类型,它应该按您的预期工作.

See typescript playground

答案 1 :(得分:1)

调试 registration 函数的执行,其中您混淆了 getEvents asyncawait 处理.then