skip to Main Content

I am new to React and was trying to render a todo-list in an exercise. My Code looks like this:

Todo Component

export default function Todo(props) {
    return {props.list.map(todo => <li>{todo}</li>)};
}

App Component

import Todo from './Todo';

const DUMMY_TODOS = [
    'Learn React',
    'Practice React',
    'Profit!'
];

export default function App() {
    return (
        <ul>
          <Todo list={DUMMY_TODOS}/>
        </ul>
    );
}

Since my code didn’t work, I tried with the following code:

Todo Component

export default function Todo(props) {
    return <ul>{props.list.map(todo => <li>{todo}</li>)}</ul>;
}

App Component

import Todo from './Todo';

const DUMMY_TODOS = [
    'Learn React',
    'Practice React',
    'Profit!'
];

export default function App() {
    return (
        <Todo list={DUMMY_TODOS}/>
    );
}

And this worked.

For me, both of them are basically the same thing. So I don’t get it why the first solution didn’t work and the second did. Does anyone know the reason here? Thanks!

2

Answers


  1. In your first version, change return {props.list.map(todo => <li>{todo}</li>)}; to <ul>{props.list.map(todo => <li key={todo}>{todo}</li>)}</ul>.

    To render an array of elements in React it is necessary to add a key property to each li element.

    The second version works, because the elements are not rendered as an array within a component, but rather as an array of strings.

    I would use the second version. It is more sustainable and can be scaled better then the first. However, you can use the first version too, if you don’t plan to reuse the rendering of the TODOs else where and this taks is only a small part of your application.

    If rendering the todos is (one of) the core feature of your project, go with verison 1.

    Login or Signup to reply.
  2. In your first attempt you are trying to return an array of JSX elements from your <Todo /> component. This is not allowed, all JSX returned elements must have a single parent (which is why your second attempt worked). Therefore, the solution is to wrap your elements in a fragment (<>{...}</>) this gives the array a parent. Furthermore, you must specify a unique key prop for each item in a rendered array.

    const DUMMY_TODOS = [
      'Learn React',
      'Practice React',
      'Profit!'
    ];
    
    function App() {
      return (
          <ul>
            <Todo list={DUMMY_TODOS}/>
          </ul>
      );
    }
    
    function Todo(props) {
      return <React.Fragment>
        {props.list.map(todo => <li key={todo}>{todo}</li>)}
      </React.Fragment>;
    }
    
    ReactDOM.createRoot(
        document.getElementById("root")
    ).render(
        <App />
    );
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search