0

Based on an example in page: https://redux.js.org/basics/usage-with-react

We have the following item:

const Todo = ({ onClick, completed, text }) => (
  <li
    onClick={onClick}
    style={{
      textDecoration: completed ? 'line-through' : 'none'
    }}
  >
    {text}
  </li>
)

Todo.propTypes = {
  onClick: PropTypes.func.isRequired,
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired
}

Also, we have the:

const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map((todo, index) => (
      <Todo key={index} {...todo} onClick={() => onTodoClick(index)} />
    ))}
  </ul>
)

Can someone please tell me what is the {...todo} on the above code?

I know that the ... operator is a spread syntax and is used lets say as [...todos, newTodoItem] (to concatenate new todo item to the old todos list). But, in the example above, todo item is not an array and it seems like it generates an object. As such for me it looks like {...todo} is equal to {todo}.

Also, what kind of properties are getting assigned on the component?

  • Spread syntax doesn't just work on arrays, see e.g. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax. *"what kind of properties are getting assigned"* - whatever kind are in the object, that's the point. See e.g. https://stackoverflow.com/questions/32363911/trouble-understanding-jsx-spread-operator, https://stackoverflow.com/questions/31048953/what-do-these-three-dots-in-react-do and most intro to React tutorials. – jonrsharpe Mar 02 '19 at 22:06

3 Answers3

2

The ... can also be used to spread objects and not just arrays. For example,

// Using rest syntax here
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; 
x; // 1
y; // 2
z; // { a: 3, b: 4 }

// Using spread here
let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }

In the above case, todos is an array of objects containing keys completed and text. Instead of manually passing the props like this -

const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map((todo, index) => (
      <Todo key={index} completed={todo.completed} text={todo.text} onClick={() => onTodoClick(index)} />
    ))}
  </ul>
)

We use the spread syntax to add the key-value pairs as props. You can think of this as syntactical sugar.

arfat
  • 136
  • 1
  • 6
0

...todo is used to pass props to Todo component . In Todo proptypes you can see there are two variable type props. so ... operator spreads( passes) it to props of Todo component

Shadab Ahmed
  • 468
  • 6
  • 20
0
const obj = {a: 1, b: 2, c: 3};

<MyComponent {...obj} /> is same as <MyComponent a={1} b={2} c={3} />. So you use spread operator ... to take out elements from object or array.

Outside React, if const test={a: 1, b:2 }, then const x = {test} //es6 feature is similar to const x = {test: test}. So this is same as const x = {test: {a: 1, b:2}}

Where as, <MyComponent {obj} /> creates an error in React because inside MyComponent, what is the name of the prop that can be used to access passed obj?. There is none. Hence the error.

function MyComponent(props) {
 // What is props.? to access obj
}

So, you use a prop with a name,

<MyComponent x={obj} />

function MyComponent(props) {
 // props.x has obj
 // props.x = obj
 console.log(props.x);
 return <div />
}

But, spread operator automatically gives props names with object keys and values as object's values as shown at the beginning of this answer.

As you said in your question, const newTodos = [...todos, newItem] creates a new array with the old todos spread out from todos and added an extra newItem. If, you did not spread todos, it would create newTodos = [[todo1, todo2],newItem].