【问题标题】:react for loop with promise value用承诺值对 for 循环做出反应
【发布时间】:2021-05-26 02:30:53
【问题描述】:

我正在努力解决反应承诺问题。我想我需要能够在 axios .then 函数之外的 for 循环中使用状态长度。目前,当我用数值替换 LEN 时,下面的代码可以工作,但如果我尝试使用 label.length 则无法工作,因为在调用 for 循环时该值不存在。任何人都可以建议处理这个问题的最佳方法吗? 我的代码很粗糙,因为我是 js 新手并做出反应。

    export default function App() {
      const [label, setLabel] = useState([]);
      const handle = useFullScreenHandle();
      const [data, setData] = useState([]);
      const token = fetch('token');
      const headers = {
        'X-CSRF-Token': token,
        'Authorization': 'Basic '+btoa('cred')  
      }
    
      React.useEffect(() => {
        axios
          .get("url", {
            headers: headers
          })
          .then(result => {
            setLabel(Object.keys(result.data).map(key => result.data[key].title));
            setData(Object.keys(result.data).map(key => result.data[key].nid));
            len=label.length
          });
      }, []);
    
    
    console.log(length)
      for (let i = 0; i < **LEN**; i++) {
        i = Number(i)
        lab = label[i];
        dat = data[i];
        var stri = ({id:String(i), category: 'cat', label:"String(i)"+i});
    
        //JSON.stringify({artist: artist, title : title});
        nodes.push (stri);
        var ed = ({id:String(i),source:String(i),target:String(i+1),label:i});
        edges.push(ed);
    
      }
    
      var datada =  ({nodes: nodes, edges:edges});
let element = 
<>
 <Sigma graph={datada}></Sigma>
  return element
</>
}

【问题讨论】:

    标签: reactjs axios es6-promise


    【解决方案1】:

    为防止datada 被不必要地重新创建并导致不必要的重新渲染,请使用useMemo 创建datada

    const datada = useMemo(() => {
      const nodes = [];
      const edges = [];
    
      for (let i = 0; i < label.length; i++) {
        i = Number(i)
        lab = label[i];
        dat = data[i];
        var stri = ({ id: String(i), category: 'cat', label: "String(i)" + i });
    
        nodes.push(stri);
        var ed = ({ id: String(i), source: String(i), target: String(i + 1), label: i });
        edges.push(ed);
      }
    
      return { nodes: nodes, edges: edges };
    }, [data, label]);
    

    这将保证仅在更改 datalabel 时重新创建 datada

    另外,在更新labeldata 时考虑使用unstable_batchedUpdates

    import { unstable_batchedUpdates } from "react-dom";
    
    // code omitted
    .then(result => {
      unstable_batchUpdates(() => {
        setLabel(Object.keys(result.data).map(key => result.data[key].title));
        setData(Object.keys(result.data).map(key => result.data[key].nid));
      });
    });
    

    这将确保labledata 同时更新,防止datada 被重新创建两次。

    【讨论】:

    • 感谢您对此的回复。您在上面建议的代码确实有效。但是根本问题仍然存在。当我试图在 .then 循环结束后调用 label.length 时,我继续看到以下行为。在页面的第一次运行中,label.length 为零。在 axios 调用之后,这个值是一个数字(339,但无论如何)。但是,for 循环对这两个值中的第一个起作用,因此运行 0 次。我想知道是否有人可以建议如何允许 label.length 返回第二个值?
    【解决方案2】:

    只需在 for 循环中获取长度,应该不会造成任何问题。

        export default function App() {
          const [label, setLabel] = useState([]);
          ......
          React.useEffect(() => {
            axios
              .get("url", {
                headers: headers
              })
              .then(result => {
                setLabel(Object.keys(result.data).map(key => result.data[key].title));
                setData(Object.keys(result.data).map(key => result.data[key].nid));
                // len=label.length   <<<< not understand what is this, len is not defined
              });
          }, []);
        
          // use label.lenght directly here
          for (let i = 0; i < label?.length; i++) {
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-18
      • 1970-01-01
      • 2023-03-17
      • 2016-10-11
      • 2015-05-05
      • 2020-05-14
      • 1970-01-01
      相关资源
      最近更新 更多