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?
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.
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.
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.
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.
I am dividing my answer in 2 sections to cover the 2 main points I see in your question.
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.
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? :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With