无效的挂钩调用React

时间:2020-08-01 13:38:34

标签: reactjs react-native react-hooks

https://reactjs.org/docs/hooks-custom.html 通过构建自己的Hook,可以将组件逻辑提取到可重用的函数中。 那就是我想要做的:将我的组件逻辑提取到其他组件的可重用函数中。

我的功能组件:

//React
import React from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
//Local
import UserPreview from './UserPreview';
import defaultContainer from '../../shared/styles/defaultContainer';
import useFetchUsers from './../../../handler/useFetchUsers';

export default function UserList(props) {
    const { users } = props;
    const dispatch = useDispatch();
    //State
    const [isLoading, setIsLoading] = React.useState(false);
    const [error, setError] = React.useState(null);

    return (
        <View style={defaultContainer}>
            <FlatList
                data={users}
                keyExtractor={(item) => item.id}
                renderItem={({ item }) => <UserPreview user={item} />}
                ListEmptyComponent={() => <Text style={styles.listEmpty}>Keine Benutzer gefunden!</Text>}
                ItemSeparatorComponent={() => <View style={styles.listSeperator} />}
                onRefresh={useFetchUsers}
                refreshing={isLoading}
                contentContainerStyle={styles.container}
            />
        </View>
    );
}

我的可重用功能:

import React from 'react';
import * as userActions from '../store/actions/user';
import { useDispatch } from 'react-redux';

export default async function useFetchUsers() {
    const [error, setError] = React.useState(null);
    const dispatch = useDispatch();
    const [isLoading, setIsLoading] = React.useState(false);

    console.log('StartupScreen: User laden');
    setIsLoading(true);
    setError(null);
    try {
        await dispatch(userActions.fetchUsers());
        console.log('StartupScreen: User erfolgreich geladen');
    } catch (err) {
        setError(err.message);
    }
    setIsLoading(false);
}

如何在用户列表的onRefresh道具中使用我的函数? 我收到此错误:无效的挂接调用 enter image description here

2 个答案:

答案 0 :(得分:2)

您正在使用useFetchUsers作为回调。钩子规则禁止这样做。

useFetchUsers应该返回一些可用作回调的函数:

export default function useFetchUsers() {
    const [error, setError] = React.useState(null);
    const dispatch = useDispatch();
    const [isLoading, setIsLoading] = React.useState(false);

    return async function() {
        console.log('StartupScreen: User laden');
        setIsLoading(true);
        setError(null);
        try {
            await dispatch(userActions.fetchUsers());
            console.log('StartupScreen: User erfolgreich geladen');
        } catch (err) {
            setError(err.message);
        }
        setIsLoading(false);
    }
}


function UserList(props) {

    ...

    const handleRefresh = useFetchUsers();

    ...

    return <FlatList onRefresh={handleRefresh} />;
}

答案 1 :(得分:0)

反应挂钩不能是异步函数。因此,根据此redux工作流程: enter image description here

您必须分派获取用户的操作,然后您的加载和错误状态应该在您的reducer中,如果您在redux旁边有任何副作用管理器(例如redux-saga),则必须在那里调用所有HTTP方法,并且组件只应调度并显示结果。另一种方法是将用户调用并提取到您的钩子中,然后通过您调度的操作将其放入您的redux存储中。 这样,加载和错误可能就在您的钩子上(在本地钩子状态,而不是在redux存储中)。

所以让我们尝试下面的代码(我已经实现了第二种方式):

import React from 'react';
import * as userActions from '../store/actions/user';
import { useDispatch } from 'react-redux';

export default function useFetchUsers() {
    const [error, setError] = React.useState(null);
    const dispatch = useDispatch();
    const [isLoading, setIsLoading] = React.useState(false);
    
    React.useEffect(() => {
      (async () => {
          console.log('StartupScreen: User laden');
          setIsLoading(true);
          setError(null);
          try {
              const res = await fetchUsers();

              dispatch(setUsers(res.data));
              console.log('StartupScreen: User erfolgreich geladen');
              setIsLoading(false);
          } catch (err) {
              setIsLoading(false);
              setError(err.message);
          }
      })()
    }, [])
}