【问题标题】:React doesn't render returned thing from async functionReact 不会渲染从异步函数返回的东西
【发布时间】:2020-07-22 17:50:17
【问题描述】:

我有一个这样的函数,这个函数的目的是创建一个交易列表并返回它们,这个函数一切都很好。没有错误。

        function ListTX() {
          (async () => {
          const arweave = Arweave.init();
          var address = window.sessionStorage.getItem("WalletAddress");
          const txids = await arweave.arql({
                op: 'and',
                expr1:
                {
                  op: 'equals',
                  expr1: 'from',
                  expr2: address
                },
                expr2:
                {
                  op: 'equals',
                  expr1: 'App-Name',
                  expr2: 'arshard'
                }
          })
          console.log(txids);
          const all_transactions = txids.map((transaction, idx) => {
              return <li key={idx}>{transaction}</li>;
          });
          console.log(all_transactions);
        return (
          <ul>
            {all_transactions}
          </ul>
          );
        })();
        }

即使all_transactions 不为空,React 也不会渲染它。同样的事情实际上适用于普通功能。


        return (
            <div>
                <Header/>
                <main>
                    <article>
                {ListTX()}
                    </article>
                </main>
            </div>
        );

这是完整的课程:

class Construct extends React.Component {
    render() {

        if (window.sessionStorage.getItem("wallet")) {
        function ListTX() {
          (async () => {
          const arweave = Arweave.init();
          var address = window.sessionStorage.getItem("WalletAddress");
          const txids = await arweave.arql({
                op: 'and',
                expr1:
                {
                  op: 'equals',
                  expr1: 'from',
                  expr2: address
                },
                expr2:
                {
                  op: 'equals',
                  expr1: 'App-Name',
                  expr2: 'arshard'
                }
          })
          console.log(txids);
          const all_transactions = txids.map((transaction, idx) => {
              return <li key={idx}>{transaction}</li>;
          });
          console.log(all_transactions);
        })();
        return (
          <ul>
            {all_transactions}
          </ul>
          );
        }
        return (
            <div>
                <Header/>
                <main>
                    <article>
                {ListTX()}
                    </article>
                </main>
            </div>
        );
      }
      else {
        return (<Redirect to="/upload_wallet"/>);
      }
    };
};
}
export default Construct;

这就是console.log(all_transactions) 返回的内容:

[
  {
    "type": "li",
    "key": "0",
    "ref": null,
    "props": {
      "children": "QWCFEHGEa0Lf2zywL_nBYmnEXhG3hLqyFcxQykhJhAc"
    },
    "_owner": null,
    "_store": {}
  },
  {
    "type": "li",
    "key": "1",
    "ref": null,
    "props": {
      "children": "cbVaHaRayhOkXR0lLL_1KFNnbyP8EEAWVQIGSKxo_2Y"
    },
    "_owner": null,
    "_store": {}
  },
  {
    "type": "li",
    "key": "2",
    "ref": null,
    "props": {
      "children": "gOrpgD3cVNEzf-u2fqI4KI5G49qaBA9jMwq-VMiQp_Q"
    },
    "_owner": null,
    "_store": {}
  },
  {
    "type": "li",
    "key": "3",
    "ref": null,
    "props": {
      "children": "PYT3WoT5dtzhyxjCQ_2dn-8ZJCqEtfZBI4-RaWJCBks"
    },
    "_owner": null,
    "_store": {}
  },
  {
    "type": "li",
    "key": "4",
    "ref": null,
    "props": {
      "children": "HJymy5uP2sqTwX5nbbzuqEXMyXliwodpIgjT5s0puxI"
    },
    "_owner": null,
    "_store": {}
  }
]

如果我这样做,它会起作用

        if (window.sessionStorage.getItem("wallet")) {
        function ListTX() {
          (async () => {
          const arweave = Arweave.init();
          var address = window.sessionStorage.getItem("WalletAddress");
          const txids = await arweave.arql({
                op: 'and',
                expr1:
                {
                  op: 'equals',
                  expr1: 'from',
                  expr2: address
                },
                expr2:
                {
                  op: 'equals',
                  expr1: 'App-Name',
                  expr2: 'arshard'
                }
          })
          console.log(txids);
          const all_transactions = txids.map((transaction, idx) => {
              return <li key={idx}>{transaction}</li>;
          });
          console.log(all_transactions);
        })();
        return (
          <p>
            test
          </p>
          );
        }

并且测试是写在网页上的。这就是为什么我怀疑它与异步函数有关,如果我尝试在异步中做同样的事情,它就不起作用。

在我们的外部函数ListTX() 中,渲染这个列表的真正方法是什么?

【问题讨论】:

  • 不应该等待异步吗?你错过了await。另外,我的建议是将您的逻辑拆分为 1)获取数据(异步)。 2) 从数据创建 JSX。然后一旦收到数据,将其设置为状态,它应该可以正常工作
  • 我不知道我是否应该等待,但await 不适用于return();
  • 渲染函数应该是一个基于 state 和 props 的纯函数。 Api 调用和其他有副作用的东西不应该在 render 中。在其中一种生命周期方法(例如,componentDidMount())中获取您的事务,然后将返回的数据设置为状态。
  • return 将返回它。由于它是一个异步函数,因此存在延迟返回。因此,ListTX() 在正常上下文中返回未定义。但是如果你让你的代码等待,它会得到正确的 JSX。但是,它不推荐。
  • 为什么ListTX() 会返回未定义?我尝试了与return(&lt;p&gt;test&lt;/p&gt;); 之类的普通函数 without list 相同的方法,它确实有效。

标签: javascript reactjs


【解决方案1】:

这是一个 CodeSandbox,展示了我建议如何构建组件。

基本上如下:

class Construct extends React.Component {
  state = {
    all_transactions: []
  };

  componentDidMount() {
    if (window.sessionStorage.getItem("wallet")) {
      (async () => {
        const arweave = Arweave.init();
        var address = window.sessionStorage.getItem("WalletAddress");
        const txids = await arweave.arql({
          op: "and",
          expr1: {
            op: "equals",
            expr1: "from",
            expr2: address
          },
          expr2: {
            op: "equals",
            expr1: "App-Name",
            expr2: "arshard"
          }
        });
        console.log(txids);
        this.setState({ all_transactions: txids });
      })();
    }
  }

  render() {
    return (
      <div>
        <Header />
        <main>
          <article>
            <ul>
              {this.state.all_transactions.map(tx => (
                <li key={tx.key}>{tx.props.children}</li>
              ))}
            </ul>
          </article>
        </main>
      </div>
    );
  }
}

export default Construct;

【讨论】:

  • TypeError: tx.props is undefined&lt;li key={tx.key}&gt;{tx.props.children}&lt;/li&gt;
【解决方案2】:

Ciao,为了“说”给 React 渲染一些东西,你必须设置 state 组件。所以我的建议是将all_transactions 存储到state 中,例如:

class Construct extends React.Component {
....
constructor(props){
  super(props);
  this.state : {
    state_all_transactions: [];
  }

 // then when you retrieve all_transactions
 ...
 this.setState({state_all_transactions: all_transactions});
 ...
}

返回时:

return (
      <ul>
        {this.stete.state_all_transactions}
      </ul>
);

试试这个,应该可以解决你的问题。

【讨论】:

  • 嗨,我认为这不会起作用,因为从函数返回的任何东西都不起作用。例如,即使我尝试在async 函数中返回return(&lt;p&gt;test&lt;/p&gt;);,它也不起作用。
  • Ciao,正如@EvanMorrison 建议的那样,尝试通过在渲染函数之外检索 state_all_transactions(例如在 componentDidMount() 中)来更改您的代码。然后,用我的例子,就可以了(我已经做了好几次了)
  • 嘿,我是 React 的初学者,我不明白如何在我的代码库中完全实现它。请给我详细的代码好吗?
【解决方案3】:

你可以像这样重写你的代码

import React, {useEffect, useState} from "react";

function ListTX() {
  const arweave = Arweave.init();
  const [txids, setTxids] = useState([]);
  useEffect(() => {
    getTxids()
  }, []);
  const getTxids = async() => {
    const address = window.sessionStorage.getItem("WalletAddress");
    const tx = await arweave.arql({
      op: 'and',
      expr1:
        {
          op: 'equals',
          expr1: 'from',
          expr2: address
        },
      expr2:
        {
          op: 'equals',
          expr1: 'App-Name',
          expr2: 'arshard'
        }
    });
    setTxids(tx);
  };
  const all_transactions = txids.map((transaction, idx) => {
    return <li key={idx}>{transaction}</li>;
  });
  console.log(all_transactions);
  return (
    <ul>
      {all_transactions}
    </ul>
  );
}

然后将其用作:

return (
    <div>
        <Header/>
        <main>
            <article>
                <ListTX/>
            </article>
        </main>
    </div>
);

【讨论】:

  • Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app
  • @BeytullahBas 这个函数是一个函数组件,这里没有错
猜你喜欢
  • 2019-03-21
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多