【问题标题】:React useState item seems to be empty when called even though item is set即使设置了项目,调用时反应 useState 项目似乎是空的
【发布时间】:2021-03-26 12:43:15
【问题描述】:

所以我试图从 Flask API 中获取数据并将其插入到 React 表中。我可以从 API 获取数据,并将其设置为 useState 中的列表,但是,当我尝试访问该列表时,它似乎是空的。

这是我的 Flask API 路由,它工作正常并返回数据。

def get_report(productname, reportname):
    mydb = client[productname]
    mycol = mydb[reportname]
    testlist = []
    instance_list = []
    for x in mycol.find({}):
        print(x)
        testlist.append({"instance": "x["Instance"]", "source": x["Source"], "target": x["Target"], "volume": x["Volume of Interference"]})
    for instance in testlist:
        instance_list.append(instance)
    response = jsonify({"data": testlist})
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

这是我的 React 组件:

import React, {useEffect, useState, useMemo} from 'react'
import { useTable } from 'react-table'
import './Report.css'

export default function Report(props){
    const [item, setItem] = useState([]);
    
    const getInstances = () => {
        let productname = props.match.params.name
        let reportname = props.match.params.reportname
        fetch("http://127.0.0.1:5000/app/reports/" + productname + "/" + reportname)
        .then(res => {
          return res.json();
        }).then(res => {
          setItem(res.data)
          console.log(res.data)
        }).catch(err => {
          console.log(err);
        })
    }

    useEffect(() => {
        getInstances();       
    },  []);

    const mockData = [
      {
      "instance": 1, "source": "test23", "target": "test53", "volume": "test123123"
      },
      {
        "instance": 2, "source": "test24242", "target": "test22324", "volume": "test223"
      }
    ]

    const COLUMNS =[
      {
          Header: 'Instance no.',
          accessor: 'instance'
      },
      {
          Header: 'Source Component',
          accessor: 'source'
      },
      {
          Header: 'Target Component',
          accessor: 'target'
      },
      {
          Header: 'Interference Volume',
          accessor: 'volume'
      },
    ];

    
    const columns = useMemo(() => COLUMNS, [])
    
    const data = useMemo(() => item, [])

    const tableInstance = useTable({
        columns,
        data
    })

    const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow} = tableInstance

    return(
        <div className = "content">
          <table className="table"{...getTableProps()}>
            <thead>
                {headerGroups.map((headerGroup) => (
                    <tr {...headerGroup.getHeaderGroupProps}>
                        {headerGroup.headers.map((column) =>(
                            <th {...column.getHeaderProps()}>{column.render('Header')}</th>
                        ))}                       
                    </tr>        
                ))}    
            </thead>
            <tbody {...getTableBodyProps()}>
                {rows.map((row) => {
                        prepareRow(row)
                        return(
                            <tr{...row.getRowProps()}>
                            {row.cells.map((cell) => (
                              <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                            ))}   
                            </tr>
                        )
                    })}
            </tbody>
          </table>            
        </div>
    )
}

当页面重新加载并且它接收到数据时,我正在调用getInstances 函数。我已经控制台记录了getInstances()函数内的返回数据(在这种情况下为res.data),它似乎是[{...},{...},{...},{的一种形式。 ..},{...} 等],与mockData 相同。

mockData 在 React 表中正确呈现,但从 API 接收的数据却没有。如果我尝试控制台记录 useState 项目,它似乎是一个空列表,这可能是它无法正确渲染的原因,但我无法理解为什么会发生这种情况。我什至尝试将mockData 插入到useState 项目中,并且出现了同样的问题。是我使用的状态错误还是我的数据类型错误?

【问题讨论】:

    标签: javascript json reactjs react-hooks use-state


    【解决方案1】:

    这是因为const data = useMemo(() =&gt; item, [])

    useMemo 返回一个记忆值。它仅在依赖项之一发生更改时重新计算记忆值。如果您不提供依赖项,它只会运行一次。使用该空依赖数组,您在获取报告之前将data 设置为由useState([]) 在第一次渲染时设置的空数组。你可以运行下面的代码 sn -p 看看它是如何工作的。

    无论如何,您不需要在这里使用useMemo,因为您只需通过在useEffect 挂钩中提供一个空的依赖项数组来获取页面加载报告。

    如果您删除const data = useMemo(() =&gt; item, []); 并使用您的item 状态作为useTable 中的数据,您的应用应该正确呈现表格:

    const tableInstance = useTable({
      columns,
      data: item,
    });
    

    function App() {
      const [items, setItems] = React.useState([]);
    
      const getInstances = () => {
        fetch('https://jsonplaceholder.typicode.com/albums')
          .then((res) => res.json())
          .then((data) => {
            setItems(data.slice(0, 2));
          });
      };
    
      React.useEffect(() => {
        getInstances();
      }, []);
    
      const dataWithEmptyDepArray = React.useMemo(() => items, []);
      const dataWithDepArray = React.useMemo(() => items, [items]);
    
      return (
        <div className="App">
          <p>
            <code>dataWithEmptyDepArray</code>
            <pre>{JSON.stringify(dataWithEmptyDepArray, null, 2)}</pre>
          </p>
          <p>
            <code>dataWithDepArray</code>
            <pre>{JSON.stringify(dataWithDepArray, null, 2)}</pre>
          </p>
          <p>
            <code>items</code>
            <pre>{JSON.stringify(items, null, 2)}</pre>
          </p>
        </div>
      );
    }
    
    ReactDOM.render(<App />, document.querySelector('#root'));
    code {
      background-color: #ededed;
      padding: .25rem .5rem;
    }
    
    p {
      border-bottom: 1px solid #ededed;
      margin-bottom: 2rem;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    【讨论】:

    • 是的,就是这样,现在它可以正常工作了!不敢相信我在这个上花了几个小时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 2022-08-03
    • 2013-07-18
    • 1970-01-01
    相关资源
    最近更新 更多