skip to Main Content

I am new to StackOverflow and asking questions and such, so bear with me, and let me know if I am missing any useful information. I am working on a productivity web app for my fiance for her job, and this is a notes section of the app. I currently have the program fetching from an API I made, storing the code in a state variable, and then I have a JSX expression in the component to map the list of notes retrieved from the server. Here is kind of how it is setup:

const Notes = () => {
    const [notesList, setNotesList] = useState([]);
    useEffect(() => {
        //loadNotes runs a fetch GET request to the server, here's what is being returned in the :
        //{notes: [{ title: "Title", content: "This is the content of the note.", lastModified: "" }, { title: "Title 2", content: "This is the content of the second note.", lastModified: "" }]}

        loadNotes().then(data => setNotesList(data.notes))
    }, [])

    return
        <div className="notes-list">{notesList.map(item => return <NoteTab title={item.title} content={item.content} lastModified={item.lastModified} />)</div>
}

Every time I run the program, I receive this error:
Objects are not valid as a React child (found: object with keys {title, content, lastModified}). If you meant to render a collection of children, use an array instead.

I have tried a bunch of different things, like spread operators on the notesList in the JSX, mapping in the useEffect function, taking off the return from the mapping, and a bunch more. Any suggestions would be great as I’ve been stuck on this for two days. Thanks!

2

Answers


  1. Here’s a problem, that return keyword should not be there. => implies return

    item => return <NoteTab…

    Fix it to:

    item => <NoteTab…

    Login or Signup to reply.
  2. There are several problems going on with the code that you are writing. Eric Fortis above pointed out one of them, which was with an arrow function, you don’t need a return statement when you return on the same line and there are no curly brackets.

    Further Breakdown:

    // notice no brackets needed for the return here
        
    const barNames = bars.map(bar => bar.name);
        
    // notice brackets ARE needed for the return in this example
    const barNames = bars.map(bar => {
      return bar.name
    });
    

    Other than that, there are some formatting errors in your code above. However, I’ll assume that those are all typos, and that you typed these in separately because otherwise, your code would not work at all (if directly copy/pasted into a react app).

    Here is a working example of your code that solves the problem you mentioned about the object child.

    import ReactDOM from 'react-dom';
    import React, { useState } from 'react';
    
    // just mocking data for example sake
    const loadNotes = async () => {
      return {
        notes: [
          {
            title: 'asdf1',
            content: 'asdf1',
            lastModified: 'asdf1',
          },
          {
            title: 'asdf2',
            content: 'asdf2',
            lastModified: 'asdf2',
          },
          {
            title: 'asdf3',
            content: 'asdf3',
            lastModified: 'asdf3',
          },
        ],
      };
    };
    
    // I think your problem locally might be here. You need to make sure that this component is not trying to render an object. One way to do that is to console log the props coming in, and ensure that title, content, and lastModified are not objects, but are string, numbers, or booleans (if you are using them like below at least). You can use objects and arrays in the templates, but other work is needed to make it work like accessing the object's properties like we are here with props object, and .map on an array for example like in the Notes component.
    const NoteTab = (props: any) => {
      return (
        <div className="note-tab">
          <h1>{props.title}</h1>
          <p>{props.content}</p>
          <p>{props.lastModified}</p>
        </div>
      );
    };
    
    // fixed the formatting issues you had
    const Notes = () => {
      const [notesList, setNotesList] = useState([]);
    
    // rewrote this function to use async/await and to destructure notes off, that way you don't have to use .then as async/await is nicer to read IMO at least.
      const fetchNotes = async () => {
        const { notes } = await loadNotes();
        notes?.length ? setNotesList(notes) : setNotesList([]);
      };
    
      useEffect(() => {
        fetchNotes();
      }, []);
    
      return (
        <div className="notes-list">
          {notesList?.map(item => (
            <NoteTab
              title={item.title}
              content={item.content}
              lastModified={item.lastModified}
            />
          ))}
        </div>
      );
    };
    
    const App = () => {
      return <Notes />;
    };
    
    // just adding this here to make sure it's a complete react app :)
    ReactDOM.render(<App />, document.getElementById('app'));
    
    

    Hopefully that helps you a bit more.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search