Объекты недопустимы в качестве дочернего элемента React (найдено: [обещание объекта])

#javascript #reactjs #ecmascript-6 #next.js

Вопрос:

Я пытаюсь отобразить список сообщений путем сопоставления с массивом. Я делал это много раз раньше, но по какой-то причине

 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 (найдено: [обещание объекта]). Если вы хотели отобразить коллекцию дочерних элементов, вместо этого используйте массив.

Я проверил данные, возвращенные с постов визуализации, и это массив с правильными значениями и без обещаний. Что здесь происходит?

Комментарии:

1. Вы можете вернуть только 1 объект из react. Вам нужно изменить return posts.map на const someVar = posts.map, а затем вернуть <ul>{someVar}<ul></ul> … таким образом, вы возвращаете завернутый объект. reactjs.org/docs/lists-and-keys.html

2. хотя первый комментарий верен, большая проблема заключается в том, что вы пытаетесь вернуть JSX из асинхронного метода, который не будет работать. вам нужно получить свои асинхронные данные componentDidMount() и позвонить this.setState , когда ваш api вернется, вместо того, чтобы возвращать JSX напрямую

3. Я пробовал это раньше с componentWillMount, потому что предполагал, что в этом проблема, но это не сработало. Просто сделал это с помощью componentDidMount, и это сработало! Спасибо, азиум.

Ответ №1:

this.renderPosts() вернет Promise не фактические данные, и AFAIK Reactjs не будет выполнять обещания неявно render .

Тебе нужно сделать это вот так

 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>
  );
}
 

Комментарии:

1. Это также помогло medium.com/front-end-hacking/…

Ответ №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

Комментарии:

1. Это исправило это для меня — трассировка стека на самом деле не выдавала, что в этом была проблема!

2. Ни render одна функция в компонентах класса не может быть асинхронной, т. е. возвращать a Promise .

3. Точно. Вместо того, чтобы реализовывать асинхронность/ожидание непосредственно в функциональном компоненте, я добавил крючок useEffect внутри функционального компонента, как это useEffect(async () => {//code with await keyword here}, []) , и все работало нормально

4. @EranG функция асинхронности’ должна быть внутри, как это useEffect( () => { асинхронная функция fetchData(){ //код с ключевым словом await здесь } fetchData ();}, []); Обратный вызов useEffect не может быть асинхронным.

Ответ №3:

Использование Крючков Реакции:

ОБНОВЛЕНИЕ 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>
}
 

Комментарии:

1. Обратный useEffect вызов не может быть async , как указано в этой статье , на которую ссылаются в документах

2. @ajrussellaudio, но он может сделать вот так… useEffect (() = > { асинхронная функция fetchData(){ попробуйте { const res = ожидание axios.get(‘/сообщения’); setPosts(res.данные); } поймать (ошибка) { console.log(ошибка); } } fetchData(); }, []);

Ответ №4:

Бедный я

Для всех, кто использует тест на шутку

И при попытке вызвать функцию дети затем получили эту ошибку

пожалуйста, проверьте:

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

НЕ

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

Ответ №5:

Если вы используете Next.js вы можете использовать это: Поместите свои коды в {}, если у вас есть какое-то соединение или какие-то вычисления, на которые требуется время, добавьте await свои коды в {}.

 import { useEffect } from 'react'

useEffect(async () => {.......},[])