javascript - Obiectele nu sunt valide ca un copil React (găsit: [object Promise])


Încerc să afișez o listă de postări prin maparea unui array. Am făcut asta de multe ori înainte, dar dintr-un motiv oarecare

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

Tot ce primesc este:

Eroare neașteptată: Obiectele nu sunt valide ca un copil React (s-a găsit: [object Promise]). Dacă intenționai să redai o colecție de copii, folosește în schimb un array.

Am verificat datele returnate de renderPosts și este un array cu valorile corecte și fără promisiuni. Ce se întâmplă aici?

Răspuns #1

Am primit, de asemenea, aceeași mesaj de eroare atunci când am creat un component funcțional asincron. Componentele funcționale nu ar trebui să fie asincrone.

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

jsfiddle

Răspuns #2

`this.renderPosts()` va returna un `Promise` și nu datele efective, și după câte știu, Reactjs nu va rezolva Promises implicit în `render`.

Trebuie să o faci așa

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

Răspunsul #3

Folosind React Hooks:

ACTUALIZARE 2020-08-01: Modificat conform sugestiei lui @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>
}