0

我想将此反应类组件转换为反应钩子组件。我转换了大部分代码,现在我需要帮助来转换渲染函数和返回函数之间的代码部分。

这是类组件:

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>
        );
    }
}

这是我创建的新反应钩子组件。正如我之前提到的,它还没有完成。

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>
        );
    }

这些是我转换代码所采取的步骤: 使用 Hooks 将 React 类组件转换为 React 函数式组件的 10 个步骤

4

2 回答 2

2

首先,来自 componentDidMount 的逻辑应该在 useEffect 挂钩中,你做对了。但是,您需要添加一个空数组作为依赖数组,这将确保 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);
        });
}, []);

这样,您应该根据组件的状态有条件地呈现 JSX 元素,如状态所定义start

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>
    }
  <>
);
于 2020-05-29T15:58:55.690 回答
1

现在你的 fetch 请求在每个渲染上运行,如果你想模拟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

于 2020-05-29T15:54:35.330 回答