Как получить из API, используя useReducer и useEffect, при этом оставляя запрос - PullRequest
1 голос
/ 26 января 2020

После этого превосходного руководства У меня есть пользовательский хук, который автоматически обновляется при изменении URL-адреса API. Мне нужно такое поведение, но я также хочу иметь возможность запрашивать мои компоненты по требованию.

const useDataApi = (initialUrl, initialData) => {
    const [url, setUrl] = useState(initialUrl);
    const [state, dispatch] = useReducer(dataFetchReducer, {
        isLoading: false,
        isError: false,
        data: initialData,
    });

    useEffect(() => {
        const fetchData = async () => {
            dispatch({ type: 'FETCH_INIT' });
            try {
                const result = await axios(url);
                dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
            } catch (error) {
                dispatch({ type: 'FETCH_FAILURE' });
            }
        };
        fetchData();
    }, [url]);

    return [state, setUrl];
};

Если я позвоню setUrl из моего компонента, дважды передав ему один и тот же URL-адрес (например, из-за кнопки refre sh onClicked), он не будет повторно получен, поскольку useEffect не обнаружит изменений в зависимости URL.

Как лучше всего включить желаемое поведение?

1 Ответ

0 голосов
/ 26 января 2020

Согласно вашему требованию вы можете использовать другое состояние attempt для изменения каждый раз, когда вы вызываете метод updateUrl. Вместо прямой экспозиции setUrl экспозиция updateUrl решит проблему.

const useDataApi = (initialUrl, initialData) => {
    const [url, setUrl] = useState(initialUrl);
    const [attempt, setAttempt] = useState(false);
    const [state, dispatch] = useReducer(dataFetchReducer, {
        isLoading: false,
        isError: false,
        data: initialData,
    });

    useEffect(() => {
        const fetchData = async () => {
            dispatch({ type: 'FETCH_INIT' });
            try {
                const result = await axios(url);
                dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
            } catch (error) {
                dispatch({ type: 'FETCH_FAILURE' });
            }
        };
        fetchData();
    }, [url, attempt]);

    const updateUrl = useCallback((newUrl) => {
        setUrl(newUrl);
        setAttempt(!attempt);
    }, [newUrl, attempt]);

    return [state, updateUrl];
};

Или проверьте, можете ли вы упростить, как показано ниже.

const useDataApi = (initialUrl, initialData) => {
    const [state, dispatch] = useReducer(dataFetchReducer, {
        isLoading: false,
        isError: false,
        data: initialData,
    });

    const setUrl = useCallback((url) => {
        const fetchData = async () => {
            dispatch({ type: 'FETCH_INIT' });
            try {
                const result = await axios(url);
                dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
            } catch (error) {
                dispatch({ type: 'FETCH_FAILURE' });
            }
        };
        fetchData();
    }, []);

    useEffect(() => setUrl(initialUrl), []);

    return [state, setUrl];
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...