【问题标题】:Invalid hook call React无效的钩子调用 React
【发布时间】:2020-08-01 13:38:34
【问题描述】:

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

我的功能组件:

//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 属性中使用我的函数? 我收到此错误:无效的挂钩调用

【问题讨论】:

    标签: reactjs react-native react-hooks


    【解决方案1】:

    您正在使用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} />;
    }
    

    【讨论】:

    【解决方案2】:

    React 钩子不能是异步函数。所以根据这个redux工作流程:

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

    那么让我们试试这段代码(我已经实现了第二种方式):

    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);
              }
          })()
        }, [])
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-08
      • 2020-02-08
      • 2020-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多