【问题标题】:Make ReactJS render after Axios request is completedAxios 请求完成后让 ReactJS 渲染
【发布时间】:2020-07-22 06:12:13
【问题描述】:

我正在使用 axios 请求触发我的后端 (expressJS) 向我的 Heroku Postgres 数据库 ('/getImageData') 发出请求,这可以在我的 Annotator.js 中看到文件。

    const getImageData = async (id) => {
    try {
        return await axios.get('/getImageData', {
            params: {
                id: id
            }
        }
        )
    }
    catch (err) {
        console.error(err);
    }
}

在这个 Annotator.js 文件的主函数中,我试图调用这个方法来获取数据并将其返回到 ReactImageAnnotate 组件中,如下所示:

function AgileAnnotator() {
    let content = false;
    let data = null;
    const { id } = useParams();

    const imageData = getImageData(id)
        .then(response => {
            if (response != undefined && response != null) {
                const row = response.data.rows[0];
                console.log(row);
                console.log(JSON.stringify(row));
                content = true;
                data = (
                    <div>
                        <ReactImageAnnotate
                            selectedImage={row.selectedimage}
                            taskDescription={row.taskdescription}
                            images={row.images}
                            regionClsList={row.regionclslist}
                            enabledTools={row.enabledtools}
                            onExit={onExit}
                        />
                    </div>
                )
            }
            else {
                data = (
                    <div>
                        <h1>Error.</h1>
                    </div>
                )
            }

        })
        .catch(error => {
            console.error(error);
            data = (
                <div>
                    <h1>Error.</h1>
                </div>
            )
        })
    
    if (data == null) {
        console.log("Returning null");
        return null;
    }
    return ({ data });
}
export default AgileAnnotator;

问题在于它返回的是 null,而不是我假设的实际数据,因为它在 Axios 获取数据之前就已呈现。

这是我使用此 Annotator.js 文件的主要 App.js 文件:

import React from 'react';
import './App.css';
import {
  BrowserRouter as Router,
  Switch,
  Route
} from 'react-router-dom'

import AgileAnnotator from './components/Annotator';

    
    const App = () => (
      <Router>
        <Switch>
          <Route path="/:id">
            <AgileAnnotator />
          </Route>
        </Switch>
      </Router>
    )
    export default App;

它在控制台中显示正在获取数据,但我也可以看到它正在返回 null,如此处所示,每当我转到 at x.x.x/2 时:

我刚刚尝试在代码中的每个点返回 ',而不是将它们设置为 data 变量。

总之,一旦 Axios 完成获取数据,我将尝试渲染 ReactImageAnnotate 元素。我对 ReactJS 很陌生,如果这很简单,我很抱歉!

非常感谢!

【问题讨论】:

    标签: javascript reactjs axios


    【解决方案1】:

    这个想法是使用两个钩子:

    1. useState 将您的代表数据组件与实际数据连接起来
    2. useEffect 用于从服务器获取数据和更新数据。

    组件接收数据作为道具。数据变化 = 组件更新。

    模板是这样的:

    const App = () => {
      const [data, setData] = useState(null) //initial state is null
      
      useEffect(()=>{
        const url = 'https://yoururl.com'
        axios(url).then(({data}) => {
           setData(data)
        })
      },[]) // empty array makes hook working once
    
      return data && <ComponentRepresentingData data={data} /> // best place to show loading process or the data itself when received
    
    

    【讨论】:

      【解决方案2】:

      更改变量不会导致组件在 react 中重新渲染,要重新渲染组件,必须更改状态或强制重新渲染 - 此外,在上下文中使用 var/let/const 定义的变量(在本例中为函数)将在重新创建上下文时始终被覆盖。

      由于您使用的是 react 函数组件,您应该使用 useState 钩子在请求完成后重新渲染您的组件,并使用 useEffect 确保您只请求一次,而不是每次重新渲染。

      import { useEffect, useState } from "react";
      function AgileAnnotator() {
          let content = false;
          const { id } = useParams();
          const [ imageData, setImageData ] = useState(undefined);
      
          useEffect(()=> getImageData(id)
              .then(response => {
                  if (response != undefined && response != null) {
                      const row = response.data.rows[0];
                      console.log(row);
                      console.log(JSON.stringify(row));
                      content = true;
                      setImageData(row);
                  }
                  else {
                      setImageData(new Error("response is null/undefined"));
                  }
      
              })
              .catch(error => {
                  console.error(error);
                  setImageData(error);
              }), [id]);
          
          if (imageData == null) {
              console.log("Returning null");
              return null; // This should really return a placeholder / spinner, though opt for the former
          }
          if (imageData instanceof Error) {
              console.error(imageData);
              return (
                          <div>
                              <h1>Error.</h1>
                          </div>
                      );
          }
          return (
                      <div>
                          <ReactImageAnnotate
                                selectedImage={imageData.selectedimage}
                                taskDescription={imageData.taskdescription}
                                images={imageData.images}
                                regionClsList={imageData.regionclslist}
                                enabledTools={imageData.enabledtools}
                                onExit={onExit}
                          />
                      </div>
                  );
      }
      export default AgileAnnotator;
      

      【讨论】:

      • 您忘记了 useEffect 的依赖项数组
      • 谢谢,忘记了(有一段时间没用过 React Hooks)
      猜你喜欢
      • 1970-01-01
      • 2015-05-23
      • 2021-01-29
      • 2019-05-20
      • 2018-10-13
      • 2019-01-19
      • 2022-01-26
      相关资源
      最近更新 更多