首页 > 解决方案 > 将 React 函数式组件转换为 Hook

问题描述

在尝试学习全栈开发时,我正在尝试本教程(https://www.freecodecamp.org/news/create-a-react-frontend-a-node-express-backend-and-connect-them-together- c5798926047c/ ) 在 React-Express-Node 基本应用程序上。但是,它是使用功能组件而不是钩子编写的。我正在尝试将此部分转换为钩子:

constructor(props) {
    super(props);
    this.state = { apiResponse: "" };
}

callAPI() {
    fetch("http://localhost:9000/testAPI")
        .then(res => res.text())
        .then(res => this.setState({ apiResponse: res }));
}

componentWillMount() {
    this.callAPI();
}

在渲染部分使用这个:

<p className="App-intro">;{this.state.apiResponse}</p>

我试过这个:

  const [apiResponse, setApiResponse] = useState();
   useEffect(() => {
     const fetchApiResponse = async () => {
       const result = await (
         'http://localhost:9000/testAPI'
       );
       setApiResponse(result);
       console.log("apiResponse " + apiResponse);
     };
     fetchApiResponse();
   });

但 apiResponse 的 console.log 始终显示为未定义。我知道我一定做错了什么,但我无法弄清楚。

标签: node.jsreactjsreact-hooks

解决方案


你的尝试并不遥远。

有两个问题:

问题1。

为了获得与componentWillMount(旁注 - 这是一种已弃用的方法,使用componentDidMountconstructor)相同的效果,您需要告诉useEffect仅在挂载时运行一次。为此,您给它一个空的依赖项数组。

useEffect(() => {
// do stuff
}, []); // empty array as second argument

通过不提供第二个参数,效果将运行每个渲染。

问题 2。

状态更新是异步的。这意味着您不能apiResponse在更新后立即控制台日志并期望它包含新值。

为了解决这个问题,只需在钩子外的函数体中使用 console.log 即可。

这是一个简化的示例:

const {useState, useEffect} = React;

const Example = () => {
  const [apiResponse, setApiResponse] = useState();
  
   useEffect(() => {
     const fetchApiResponse = () => {
       const result = 'test';
       setApiResponse(result);
       // Will not be updated
       console.log("wrong: apiResponse ", apiResponse);
     }
     fetchApiResponse();
   }, []);
   
   // Will be updated
   console.log("right: apiResponse ", apiResponse);
   
   return <span />
}

ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>


推荐阅读