0

I am getting an error in my console,

my JSON is here https://dev.justinblayney.com/wp-content/uploads/2020/12/main-menu.json_.zip

Warning: Each child in a list should have a unique "key" prop.

What displays on my page is (So they are all unique, so WTF react)

KEY: 2429 KEY: 2430 KEY: 3859 KEY: 2421 KEY: 2802 KEY: 2428

On a side note, I'm discovering that using a function is a terrible way to get a JSON file, I also get memory leak warnings and every tutorial I see online uses classes or axios

Check the render method of MyRoutes. See https://reactjs.org/link/warning-keys for more information. MyRoutes@http://localhost:3000/react-wordpress-headless/static/js/main.chunk.js:63:81 div Router@http://localhost:3000/react-wordpress-headless/static/js/0.chunk.js:35747:30 BrowserRouter@http://localhost:3000/react-wordpress-headless/static/js/0.chunk.js:35367:35 App@http://localhost:3000/react-wordpress-headless/static/js/main.chunk.js:94:1

    function MyRoutes() {
    
    const [myrt, setMyrt] = useState([]); 
  
    
    useEffect(() => {
        fetch("main-menu.json" ,{
      headers : { 
        'Content-Type': 'application/json',
        'Accept': 'application/json'
       }
    })
        .then(res => res.json())
    
        .then(json =>{
             setMyrt(json.items)}
              )
         });
        
    
    return (
        <>
            {Object.keys(myrt).map((ky, idx)=> (
            <>
             <h2>KEY: {myrt[ky].ID} </h2>
        <Route exact path={`/${myrt[ky].slug}`} component={Page} key={myrt[ky].ID}  /></>
            ))} 
        </>
  
    );
}
Justin Blayney
  • 671
  • 1
  • 6
  • 23

4 Answers4

3

The key prop should be defined on the first most element, in your case it is React.Fragment.

function MyRoutes() {
  const [myrt, setMyrt] = useState([]);

  useEffect(() => {
    fetch('main-menu.json', {
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
      },
    })
      .then((res) => res.json())

      .then((json) => {
        setMyrt(json.items);
      });
  });

  return (
    <>
      {Object.keys(myrt).map((ky, idx) => (
        <React.Fragment key={ky}>
          // ------------^
          <h2>KEY: {myrt[ky].ID} </h2>
          <Route exact path={`/${myrt[ky].slug}`} component={Page} key={myrt[ky].ID} />
        </React.Fragment>
      ))}
    </>
  );
}
felixmosh
  • 32,615
  • 9
  • 69
  • 88
1

The key property is needed on the first-level of the list child element, thus I think in your example the React fragment within your .map needs to have this key.

andi1984
  • 676
  • 10
  • 27
1

You need the key on the top component/tag that it's rendering on the map. Example: if you use a div

<div key={myrt[ky].ID} >
    <h2>KEY: {myrt[ky].ID} </h2>
    <Route exact path={`/${myrt[ky].slug}`} component={Page} />
</div>
Brian Rigoni
  • 11
  • 1
  • 2
1

For your memory leak you are calling the function get the JSON file infinite times because you have not specified any dependencies in the useEffect. So you set the data, it rerenders, then fetches again forever

    useEffect(() => {
        fetch("main-menu.json" ,{
      headers : { 
        'Content-Type': 'application/json',
        'Accept': 'application/json'
       }
    })
        .then(res => res.json())
    
        .then(json =>{
             setMyrt(json.items)}
              )
         }, [] /* Adding this only runs this once */);
topched
  • 765
  • 3
  • 11