【问题标题】:Convert a react class component to react hooks component将反应类组件转换为反应钩子组件
【发布时间】:2020-09-17 06:09:45
【问题描述】:

我想把这个 react 类组件转换成一个 react hooks 组件。 我转换了大部分代码,现在我需要帮助来转换渲染函数和返回函数之间的代码部分。

这是类组件:

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

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

【问题讨论】:

    标签: javascript reactjs react-hooks react-class-based-component


    【解决方案1】:

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

    这样,您应该根据 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>
        }
      <>
    );
    

    【讨论】:

      【解决方案2】:

      现在您的 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

      【讨论】:

      • 渲染方法后面的那几行代码呢?我怎样才能改变它?
      猜你喜欢
      • 1970-01-01
      • 2019-09-01
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2021-06-08
      • 2022-01-15
      相关资源
      最近更新 更多