将 react class 组件转换为 react hooks 组件

Convert a react class component to react hooks component

我想将此 React class 组件转换为 React Hooks 组件。 我转换了大部分代码,现在我需要帮助来转换渲染和 return 函数之间的部分代码。

这是 class 组件:

class LoginGoogle extends React.Component {
    state = {
        loading: true,
        error: null,
        data: {},
    };

    componentDidMount() {
        fetch(`/api/auth/google/callback${this.props.location.search}`, { headers: new Headers({ accept: 'application/json' }) })
            .then((response) => {
                if (response.ok) {
                    return response.json();
                }
                throw new Error('Something went wrong!');
            })
            .then((data) => {
                this.setState({ loading: false, data });
            })
            .catch((error) => {
                this.setState({ loading: false, error });
                console.error(error);
            });
    }

    render() {
        const { loading, error, data } = this.state;
        if (loading) {
            return <Layout>Loading....</Layout>;
        }

        if (error) {
            return (
                <Layout>
                    <div>
                        <p>Error:</p>
                        <code className="Code-block">{error.toString()}</code>
                    </div>
                </Layout>
            );
        }

        return (
            <Layout>
                <div>
                    <details>
                        <summary>Welcome {data.user.name}</summary>
                        <p>Here is your info: </p>
                        <code className="Code-block">{JSON.stringify(data, null, 2)}</code>
                    </details>
                </div>
            </Layout>
        );
    }
}

这是我创建的新 React Hooks 组件。正如我之前提到的,它还没有完成。

function LoginGoogle (props) {

    const [start, setStart] = useState(
        {
        loading: true,
        error: null,
        data: {},
           }
    )

    useEffect(() => {
        fetch(`/api/auth/google/callback${props.location.search}`, { headers: new Headers({ accept: 'application/json' }) })
            .then((response) => {
                if (response.ok) {
                    return response.json();
                }
                throw new Error('Something went wrong!');
            })
            .then((data) => {
                setStart({ loading: false, data });
            })
            .catch((error) => {
                setStart({ loading: false, error });
                console.error(error);
            });
    })


        const { loading, error, data } = this.state;
        if (loading) {
            return <Layout>Loading....</Layout>;
        }

        if (error) {
            return (
                <Layout>
                    <div>
                        <p>Error:</p>
                        <code className="Code-block">{error.toString()}</code>
                    </div>
                </Layout>
            );
        }

        return (
            <Layout>
                <div>
                    <details>
                        <summary>Welcome {data.user.name}</summary>
                        <p>Here is your info: </p>
                        <code className="Code-block">{JSON.stringify(data, null, 2)}</code>
                    </details>
                </div>
            </Layout>
        );
    }

这些是我转换代码的步骤: 10 Steps to Convert React Class Component to React Functional Component with Hooks!

现在你的获取请求是 运行ning 每次渲染,如果你想模拟 componentDidMount 行为,你需要将一个空的依赖数组传递给 useEffect

useEffect(() => {
    fetch(`/api/auth/google/callback${props.location.search}`, { headers: new Headers({ accept: 'application/json' }) })
        .then((response) => {
            if (response.ok) {
                return response.json();
            }
            throw new Error('Something went wrong!');
        })
        .then((data) => {
            setStart({ loading: false, data });
        })
        .catch((error) => {
            setStart({ loading: false, error });
            console.error(error);
        });
}, []) // See the empty dependency array

通过添加一个空的依赖列表,它会运行一次。

const { loading, error, data } = this.state

变成

const {loading, error, data} = start

首先,componentDidMount 的逻辑应该在 useEffect 挂钩中,您做对了。但是,您需要添加一个空数组作为依赖数组,这将确保在 mount:

上调用一次 HTTP 请求
useEffect(() => {
    fetch(`/api/auth/google/callback${props.location.search}`, { headers: new Headers({ accept: 'application/json' }) })
        .then((response) => {
            if (response.ok) {
                return response.json();
            }
            throw new Error('Something went wrong!');
        })
        .then((data) => {
            setStart({ loading: false, data });
        })
        .catch((error) => {
            setStart({ loading: false, error });
            console.error(error);
        });
}, []);

因此,您应该根据 start 状态定义的组件状态有条件地呈现 JSX 元素:

const { data, error, loading } = start;

return (
  <>
    {error && (
       <Layout>
         <div>
           <p>Error:</p>
           <code className="Code-block">{error.toString()}</code>
           </div>
       </Layout>
    )}
    {data && (
      <Layout>
        <div>
           <details>
             <summary>Welcome {data.user.name}</summary>
             <p>Here is your info: </p>
             <code className="Code-block">{JSON.stringify(data, null, 2)}</code>     </details>
         </div>
      </Layout>
    )}
    {
      loading && <Layout>Loading....</Layout>
    }
  <>
);