自定义钩子的异常行为

时间:2019-08-30 15:30:38

标签: react-hooks

我已经制作了自定义的axios挂钩。

// src/useAxios.js

import { useState, useEffect } from 'react';
import axios from 'axios';

export const useAxios = url => {
    const [state, setState] = useState({ data: null, loading: false });

    useEffect(() => {
        setState(currentState => ({
            ...currentState,
            loading: true
        }));

        axios.get(url).then(response => {
            setState(currentState => ({
                ...currentState
                data: response.data.body
            }));
        });

        setState(currentState => ({
            ...currentState,
            loading: false
        }));
    }, [url]);

    return state;
};

应用程序组件使用此钩子。

// src/App.js    

import React from 'react';
import { useAxios } from './useAxios';

const App = () => {
    const { data, loading } = useAxios(
        'https://jsonplaceholder.typicode.com/posts/1'
    );
    console.log(loading);

    return <div>{loading ? 'loading..' : data}</div>;
};

export default App;

我已将console.log添加到App组件以检查其工作原理。

它记录false false false

我期望的是false true true false,因为变量加载发生了四次变化。

但是,如果我像下面那样更改钩子,它将正确记录false true false

import { useState, useEffect } from 'react';
import axios from 'axios';

export const useAxios = url => {
    const [state, setState] = useState({ data: null, loading: false });

    useEffect(() => {
        setState(currentState => ({
            ...currentState,
            loading: true
        }));

        axios.get(url).then(response => {
            setState(currentState => ({
                loading: false,
                data: response.data.body
            }));
        });
    }, [url]);

    return state;
};

出什么问题了?

我们不能在useState中多次使用useEffect吗?

第一个挂钩有什么问题?

1 个答案:

答案 0 :(得分:0)

问这个很傻。

第一个记录“ false false false”的原因是

由于setState批处理在一起,因此无法记录true。

我犯了致命的错误,那就是我在诺言之后而不是在其中使用了useState。

这是正确的代码。

import { useState, useEffect } from 'react';
import axios from 'axios';

export const useAxios = url => {
    const [state, setState] = useState({ data: null, loading: false });

    useEffect(() => {
        setState(currentState => ({
            ...currentState,
            loading: true
        }));

        axios.get(url).then(response => {
            setState(currentState => ({
                ...currentState,
                data: response.data.body
            }));

            setState(currentState => ({
                ...currentState,
                loading: false
            }));
        });
    }, [url]);

    return state;
};

如我所料,它会记录false true true true false