1

This is the structure of the json being fetched. I am trying to render some of the nested threads data to a web page with react.

enter image description here

import react, {useState, useEffect} from "react";
import axios from 'axios'
import ReactJson from 'react-json-view'

const FeaturedBoards = () => {
    const [boards, setBoards] = useState([{page: '', threads: {}}]); 

useEffect(() => {
    fetchBoards();
}, []);

const fetchBoards = () => {
    axios.get('https://a.4cdn.org/po/catalog.json')
    .then((res) => {
        console.log(res.data);
        setBoards(res.data);
    })
    .catch((err) => {
        console.log(err);
    });
};
    if(boards === 0) {
        return <div>Loading...</div>;
    }
    else{
    return (
        <div>
            <h1>Featured Boards</h1>
            <div className='item-container'>
                {boards.map((board) => (
                    <div className='board' key={board.id}>
                        <p>{board['threads']}</p>
                    </div>
                ))}
            </div>
        </div>
    );
    }
};

export default FeaturedBoards;

I have tried everything to display some of the nested threads data but nothing comes up. I've tried doing a second call to map on board but no luck, storing it in a variable and calling from that still nothing. Am I doing something totally wrong?

enter image description here

  • Since the `threads` properties in your API data appear to be arrays, why are you initialising it as an object with `useState([{page: '', threads: {}}])`? That's what is causing the error. Also, why initialise with a single-element array in the first place? Why not just `useState([])`? – Phil Oct 25 '21 at 02:44
  • my thinking was you had to provide a template structure to be filled in. When I switch useState to that it gives me this error. `Error: Objects are not valid as a React child (found: object with keys {no, sticky, closed, now, name, sub, com, filename, ext, w, h, tn_w, tn_h, tim, time, md5, fsize, resto, capcode, semantic_url, replies, images, omitted_posts, omitted_images, last_replies, last_modified}). If you meant to render a collection of children, use an array instead.` – meanthatmuchtoyou Oct 25 '21 at 02:48
  • To this what you said to try `useState([])` hard to repost the whole code down here lol – meanthatmuchtoyou Oct 25 '21 at 02:53
  • `const [boards, setBoards] = useState([]); ` – meanthatmuchtoyou Oct 25 '21 at 02:54
  • Each _board_ `threads` is an array of objects (presumably with properties like `no`, `sticky`, `closed`, etc). `

    {board['threads']}

    ` just doesn't make sense for that data structure. As the error message says, _"Objects (like the ones in `board.threads`) are not valid as a React child"_
    – Phil Oct 25 '21 at 02:54
  • That was the thing when i use one of those expected keywords like `board['com']` nothing shows up but in the console logs all the data is showing up in the response but then nothing renders on the screen – meanthatmuchtoyou Oct 25 '21 at 02:57

1 Answers1

1

I believe this is more fully answered by How can I access and process nested objects, arrays or JSON?. but to explain for this particular data structure, keep reading.


Look at your actual data... boards is an array. Each element in it is an object with page (int) and threads (array) properties. Each threads array element is an object with other properties. You can use map to iterate arrays and return a JSX representation of the objects within.

For example

const [boards, setBoards] = useState([]); // start with an empty array
const [loading, setLoading] = useState(true)

useEffect(() => {
  fetchBoards().then(() => setLoading(false))
}, []);

const fetchBoards = async () => {
  const { data } = await axios.get('https://a.4cdn.org/po/catalog.json')
  setBoards(data)
}

return loading ? <div>Loading...</div> : (
  <div>
    <h1>Featured Boards</h1>
    <div className="item-container">
      {boards.map(board => (
        <div className="board" key={board.page}> <!--  note "page", not "id" -->
          {board.threads.map(thread => (
            <p>{thread.name}</p>
            <p>{thread.sub}</p>
            <p>{thread.com}</p>
            <!-- etc -->
          ))}
        </div>
      ))}
    </div>
  </div>
)
Phil
  • 157,677
  • 23
  • 242
  • 245
  • Worked! thank you that was what I was trying to do, does changing the key={} from id to page do anything? – meanthatmuchtoyou Oct 25 '21 at 03:22
  • See https://reactjs.org/docs/lists-and-keys.html#keys. Your `board` objects don't appear to have `id` properties so you'd be setting each `key` to `undefined` which would produce _"Warning: Each child in a list should have a unique "key" prop."_ – Phil Oct 25 '21 at 03:26
  • ahhh makes sense from errors I had been seeing, I'll check that out thanks. – meanthatmuchtoyou Oct 25 '21 at 18:56