在 React Router v4 中渲染异步组件

IT技术 javascript reactjs asynchronous react-router react-router-v4
2021-04-18 07:29:02

我想根据它从下面的 api 接收到的有效负载呈现一个组件

<Route path="/foo/bar" render={() => {
  return (get('/some/api').then((res) => {
    return <Baz data={res.data} />
          }).catch((err) => console.log))
        }} />

但我收到错误:

Objects are not valid as a React child (found: [object Promise]). If you 
meant to render a collection of children, use an array instead. 

即使我确实换Baz[]

1个回答

不幸的是,最新版本的 React - 16。异步渲染还不是一个选项。

使用 React Router v4,组件renderpropsRoute期望返回一个有效的 React 元素或 React 元素数组,因此,它不接受从你的函数返回的 Promise 对象。

然而,使用当前版本的 React 和 React Router 来实现你想要的并不是不可能的。你只需要稍微调整你的代码。render应该返回一个 React 组件,而不是返回 Promise,然后您可以根据该组件内的异步值进行条件渲染。

它应该看起来像:

<Route path="/foo/bar" render={BazWrapper} />


class BazWrapper extends React.Component {

    // Do asynchronous action here
    async componentDidMount() {
       try {
          const apiValue = await get('/some/api');
          this.setState({ apiValue })
       } catch(err) {
          // error handling
       }
    }

    render() {
        const { apiValue } = this.state; 
        return <Baz data={apiValue} />;
    }

}

通过setState在异步调用完成后调用,你让 React Component 知道数据已经准备好,它应该重新渲染组件。

另外,只是一个建议,但是可以通过传递apiValuechildren而不是硬编码<Baz />包装类中来使包装类更具可重用性
2021-05-27 07:29:02
您的解决方法使 Baz 组件呈现两次,第一次没有数据。
2021-05-27 07:29:02
这不是一种解决方法,它只是 React 和 React Router 的工作原理。此外,React开发团队自己也推荐componentDidMount用于从外部源获取数据,如果您不希望Baz组件在没有数据的情况下进行渲染,只需将其设置为条件渲染即可。
2021-05-31 07:29:02
小更正,应该render={BazWrapper}或者render={props => <BazWrapper {...props} />}
2021-06-02 07:29:02
嗨@azium,感谢您的评论,我进行了更正。渲染函数返回 <Baz> 绝对只是一个基于问题提供的示例。
2021-06-10 07:29:02