Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use React createFragment?

I'm rendering a ListView in React Native, managed to fix this React warning but I don't understand how and why it works:

Warning: Any use of a keyed object should be wrapped in React.addons.createFragment(object) before being passed as a child.

// This array generates React Fragment warning.
var data1 = [{name: "bob"}, {name:"john"}]

// This array works, no warnings.
var data2 = [React.addons.createFragment({name: "bob"}),
             React.addons.createFragment({name: "john"})]

// This also works, no warnings.
var data3 = ["bob", "john"]

class Listings extends React.Component {
  constructor(props) {
    super(props)
    ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})

    this.state = {
      dataSource: ds.cloneWithRows(data),
    }
  }
  render() {
    return (
       <ListView
         dataSource={this.state.dataSource} 
         renderRow={(rowData) => <Text>{rowData}</Text>} />
    )
  }
}

What is a React Fragment? When is it needed in React? Why does a keyed object cause this warning?

like image 783
Henry Zhu Avatar asked Oct 07 '15 21:10

Henry Zhu


People also ask

When should I use React fragment?

React Fragments allow you to wrap or group multiple elements without adding an extra node to the DOM. This can be useful when rendering multiple child elements/components in a single parent component.

Why we use React fragment instead of DIV?

Therefore, React fragments are better than the 'div' tags. With React Fragment, you can render multiple elements of a component without adding extra div tags. We can write cleaner, more readable code with React Fragments. It takes up less memory and renders components faster. Each component is rendered as expected.

Why do we need keys for React lists?

A “key” is a special string attribute you need to include when creating lists of elements in React. Keys are used to React to identify which items in the list are changed, updated, or deleted. In other words, we can say that keys are used to give an identity to the elements in the lists.

Why do we use fragments in React Google it?

A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM.


1 Answers

I am dividing my answer in 2 sections to cover the 2 main points I see in your question.

Section 1: What is a React Fragment?

In order to explain what a React Fragment is, we need to take step back and talk about React Keys.

Keys help React identify which items have changed, are added, or are removed. They should be given to the elements inside an array to give the elements a stable identity (uniqueness).

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys. Here's a practical example:

render() {
    const todoItems = todos.map((todo) =>
      <li key={todo.id}>
        {todo.text}
      </li>
    );

    return todoItems;
}

It's important to note that the todoItems is actually an array of <li> elements.

Knowing that, let's move on to why you receive a warning in your use-case.

In most cases, you can use the key prop to specify keys on the elements you're returning from render, just like the example above. However, this breaks down in one situation: if you have two sets of children that you need to reorder, there's no way to put a key on each set without adding a wrapper element.

Here's the classical example from the recently updated React docs:

function Swapper(props) {
  let children;
  if (props.swapped) {
    children = [props.rightChildren, props.leftChildren];
  } else {
    children = [props.leftChildren, props.rightChildren];
  }
  return <div>{children}</div>;
}

The children will unmount and remount as you change the swapped prop because there aren't any keys marked on the two sets of children.

To solve this problem, you can use the createFragment add-on to give keys to the sets of children. Follow the enhanced example, using the createFragment here.


Section 2: But why you are getting this warning?

Anyways, the error you're getting error happens simply because you try to interpolate a JavaScript object (rather than a JSX element or string) into some JSX.

Although the error message suggests using createFragment to fix this, the reason is because you're interpolating a variable into some JSX that is not a string or JSX element, but is in fact some other kind of object!

Such a misleading warning in your use-case, isn't it? :-)

like image 189
Kaloyan Kosev Avatar answered Sep 17 '22 00:09

Kaloyan Kosev