---
title: Arrays and Keys
description: "Rendering arrays and handling keys in ReScript and React"
canonical: "/docs/react/latest/arrays-and-keys"
---
# Arrays and Keys
Whenever we are transforming data into an array of elements and put it in our React tree, we need to make sure to give every element an unique identifier to help React distinguish elements for each render. This page will explain the `key` attribute and how to apply it whenever we need to map data to `React.element`s.
## Rendering Arrays
Arrays require a special function `React.array` to convert an `array` to render as `Jsx.element`.
```res example
type todo = {id: string, text: string}
@react.component
let make = () => {
let todos = [{id: "todo1", text: "Todo 1"}, {id: "todo2", text: "Todo 2"}]
let items = Array.map(todos, todo => {
{React.string(todo.text)}
})
{React.array(items)}
}
```
```js
function Playground(props) {
var todos = [
{
id: "todo1",
text: "Todo 1"
},
{
id: "todo2",
text: "Todo 2"
}
];
var items = todos.map(function (todo) {
return JsxRuntime.jsx("li", {
children: todo.text
}, todo.id);
});
return JsxRuntime.jsx("ul", {
children: items
});
}
```
## Keys
Keys help React identify which elements have been changed, added, or removed throughout each render. Keys should be given to elements inside the array to give the elements a stable identity:
```res example
let numbers = [1, 2, 3, 4, 5]
let items = Array.map(numbers, (number) => {
{React.int(number)}
})
```
```js
var numbers = [
1,
2,
3,
4,
5
];
var items = numbers.map(function (number) {
return JsxRuntime.jsx("li", {
children: number
}, number.toString());
});
```
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:
```res prelude
type todo = {id: string, text: string}
let todos = [
{id: "todo1", text: "Todo 1"},
{id: "todo2", text: "Todo 2"}
]
let items = Array.map(todos, todo => {
{React.string(todo.text)}
})
```
```js
var todos = [
{
id: "todo1",
text: "Todo 1"
},
{
id: "todo2",
text: "Todo 2"
}
];
var items = todos.map(function (todo) {
return JsxRuntime.jsx("li", {
children: todo.text
}, todo.id);
});
```
If you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:
```res example {1..3}
let items = Array.mapWithIndex(todos, (todo, i) => {
// Only do this if items have no stable id
{React.string(todo.text)}
})
```
```js
var items = todos.map(function (todo, i) {
return JsxRuntime.jsx("li", {
children: todo.text
}, i.toString());
});
```
### Keys Must Only Be Unique Among Siblings
Keys used within arrays should be unique among their siblings. However they don’t need to be globally unique. We can use the same keys when we produce two different arrays:
```res example {6,10,17,18,25,27}
type post = {id: string, title: string, content: string}
module Blog = {
@react.component
let make = (~posts: array) => {
let sidebar =
{Array.map(posts, post => {
{React.string(post.title)}
})->React.array}
let content = Array.map(posts, post => {
{React.string(post.title)}
{React.string(post.content)}
})
{sidebar}
{React.array(content)}
}
}
let posts = [
{
id: "1",
title: "Hello World",
content: "Welcome to learning ReScript & React!",
},
{
id: "2",
title: "Installation",
content: "You can install reason-react from npm.",
},
]
let blog =
```
```js
function Playground$Blog(props) {
var posts = props.posts;
var sidebar = JsxRuntime.jsx("ul", {
children: posts.map(function (post) {
return JsxRuntime.jsx("li", {
children: post.title
}, post.id);
})
});
var content = posts.map(function (post) {
return JsxRuntime.jsxs("div", {
children: [
JsxRuntime.jsx("h3", {
children: post.title
}),
JsxRuntime.jsx("p", {
children: post.content
})
]
}, post.id);
});
return JsxRuntime.jsxs("div", {
children: [
sidebar,
JsxRuntime.jsx("hr", {}),
content
]
});
}
var Blog = {
make: Playground$Blog
};
var posts = [
{
id: "1",
title: "Hello World",
content: "Welcome to learning ReScript & React!"
},
{
id: "2",
title: "Installation",
content: "You can install reason-react from npm."
}
];
var blog = JsxRuntime.jsx(Playground$Blog, {
posts: posts
});
```
## Rendering `list` Values
In case you ever want to render a `list` of items, you can do something like this:
```res example
type todo = {id: string, text: string}
@react.component
let make = () => {
let todoList = list{
{id: "todo1", text: "Todo 1"},
{id: "todo2", text: "Todo 2"},
}
let items =
todoList
->List.toArray
->Array.map(todo => {
{React.string(todo.text)}
})
{React.array(items)}
}
```
```js
function Playground(props) {
var items = Core__List.toArray({
hd: {
id: "todo1",
text: "Todo 1"
},
tl: {
hd: {
id: "todo2",
text: "Todo 2"
},
tl: /* [] */0
}
}).map(function (todo) {
return JsxRuntime.jsx("li", {
children: todo.text
}, todo.id);
});
return JsxRuntime.jsx("div", {
children: items
});
}
```
We use `List.toArray` to convert our list to an array before creating our `array`. Please note that using `list` has performance impact due to extra conversion costs.
99% of the time you'll want to use arrays (seamless interop, faster JS code), but in some cases it might make sense to use a `list` to leverage advanced pattern matching features etc.