【问题标题】:Objects are not valid as a React child (found: [object Promise])对象作为 React 子级无效(发现:[object Promise])
【发布时间】:2021-10-02 19:38:31
【问题描述】:

我正在尝试通过数组映射来呈现帖子列表。我以前做过很多次,但出于某种原因

renderPosts = async () => {
    try {
      let res = await axios.get('/posts');
      let posts = res.data;
      return  posts.map((post, i) => {
        return (
          <li key={i} className="list-group-item">{post.text}</li>
        );
      });
    } catch (err) {
      console.log(err);
    }
  }

  render () {
    return (
      <div>
        <ul className="list-group list-group-flush">
          {this.renderPosts()}
        </ul>
      </div>
    );
  }

我得到的是:

未捕获的错误:对象作为 React 子项无效(找到:[object Promise])。如果您打算渲染一组子项,请改用数组。

我检查了从 renderPosts 返回的数据,它是一个具有正确值且没有任何承诺的数组。这是怎么回事?

【问题讨论】:

  • 您只能从反应中返回 1 个对象。您需要将 return posts.map 更改为 const someVar = posts.map,然后返回
      {someVar}
    ...这样,您将返回一个包装的对象。 reactjs.org/docs/lists-and-keys.html
  • 虽然第一条评论是正确的,但更大的问题是你试图从一个不起作用的异步方法返回 JSX。您需要在componentDidMount() 中获取您的异步数据并在您的 api 返回而不是直接返回 JSX 时调用 this.setState
  • 我以前用 componentWillMount 试过这个,因为我认为这是问题所在,但它没有用。只需使用 componentDidMount 就可以了!谢谢 azium。

标签: javascript reactjs


【解决方案1】:

this.renderPosts() 将返回 Promise 而不是实际数据,AFAIK Reactjs 不会在 render 中隐式解析 Promise。

你需要这样做

componentDidMount() {
  this.renderPosts();
}

renderPosts = async() => {
  try {
    const res = await axios.get('/posts');
    const posts = res.data;

    // this will re render the view with new data
    this.setState({
      Posts: posts
    });
  } catch (err) {
    console.log(err);
  }
}

render() {
  const posts = this.state.Posts?.map((post, i) => (
    <li key={i} className="list-group-item">{post.text}</li>
  ));

  return (
    <div>
      <ul className="list-group list-group-flush">
        {posts}
      </ul>
    </div>
  );
}

【讨论】:

【解决方案2】:

我在创建异步功能组件时也收到了相同的错误消息。功能组件不应该是异步的。

const HelloApp = async (props) =>  { //<<== removing async here fixed the issue
  return (
    <div>
      <h2>Hello World</h2>
    </div>
  )
}
ReactDOM.render(<HelloApp />, document.querySelector("#app"))

jsfiddle

【讨论】:

  • 这为我解决了问题 - 堆栈跟踪并没有真正表明这是问题所在!
  • 类组件中的render函数都不能是异步的,即返回Promise
  • 没错。我没有直接在功能组件上实现 async/await,而是在功能组件中添加了 useEffect 钩子,就像这样 useEffect(async () =&gt; {//code with await keyword here}, []) 并且一切正常
  • @EranG async func' 应该在里面这样 useEffect( () => { async function fetchData(){ //code with await keyword here } fetchData(); }, []); useEffect 回调不能是异步的。
【解决方案3】:

可怜的我

对于任何使用开玩笑测试的人

并尝试调用函数 children 然后收到此错误

请检查:

const children = jest.fn().mockReturnValueOnce(null)

不是

const children = jest.fn().mockRejectedValue(null);

【讨论】:

    【解决方案4】:

    使用 React Hooks:

    2020-08-01 更新:根据 @ajrussellaudio 的建议进行了修改。

    import React, {useState, useEffect} from "react"
    
    const ShowPosts = () => {
        const [posts, setPosts] = useState([]);
        
        useEffect( () => { 
            async function fetchData() {
                try {
                    const res = await axios.get('/posts'); 
                    setPosts(res.data);
                } catch (err) {
                    console.log(err);
                }
            }
            fetchData();
        }, []);
        return <div>{posts}</div>
    }
    

    【讨论】:

    • useEffect 回调不能是async,正如this article 中所指出的,the docs 中引用了该回调
    • @ajrusselaudio 但他可以这样做... useEffect( () => { async function fetchData(){ try { const res = await axios.get('/posts'); setPosts( res.data); } catch (err) { console.log(err); } } fetchData(); }, []);
    【解决方案5】:

    如果你使用 Next.js,你可以使用这个: 将您的代码放入 {},如果您有一些连接或一些计算需要时间,请将 await 添加到 {} 中的代码中。

    import { useEffect } from 'react'
    
    useEffect(async () => {.......},[])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      相关资源
      最近更新 更多