Ошибка React: Objects are not valid as a React child
При разработке на React вы можете столкнуться с сообщением: Objects are not valid as a React child (found: object with keys {type, key, props, _owner, _store}). If you meant to render a collection of children, use an array instead. Эта ошибка возникает, когда React пытается отобразить объект, а не строку, число или React-элемент. В статье разберём типичный случай - сохранение JSX-компонентов в localStorage - и покажем правильное решение.
Почему возникает ошибка?
Ошибка появляется, когда вы передаёте в JSX-разметку объект, который не является React-элементом. В вашем коде:
- Вы сохраняете JSX-компонент (
<div key={...}>777</div>) в массив и записываете его черезJSON.stringifyвlocalStorage. - При загрузке страницы
JSON.parseпревращает этот элемент обратно в обычный объект JavaScript (с ключамиtype,key,propsи т.д.), а не в React-элемент. - React не умеет рендерить такие объекты - отсюда ошибка.
Как исправить: не сохраняйте JSX в localStorage
JSX - это синтаксический сахар, который компилируется в вызовы React.createElement. Результат - объект, который не может быть сериализован в JSON и обратно. Вместо этого сохраняйте только данные, необходимые для создания компонентов.
Правильный подход
Храните в localStorage только идентификаторы или простые данные, а JSX-элементы генерируйте на лету при рендере. Пример:
function App() {
const [keys, setKeys] = useState(JSON.parse(localStorage.getItem('keys')) || []);
function addComponent() {
const newKey = Math.floor(Math.random() * 10000);
const updatedKeys = [...keys, newKey];
setKeys(updatedKeys);
localStorage.setItem('keys', JSON.stringify(updatedKeys));
}
return (
<>
<button onClick={addComponent}>click</button>
<div>{keys.map(key => <div key={key}>777</div>)}</div>
</>
);
}Здесь мы сохраняем только массив ключей, а JSX-элементы создаются в процессе рендеринга с помощью map. Это решает проблему и сохраняет функциональность.
Альтернативное решение: хранение строк и последующая компиляция
Если вам критично хранить именно структуру компонентов, можно сериализовать её в строку (например, в формате JSON с описанием типа и свойств), а при загрузке воссоздавать React-элементы через React.createElement. Но этот способ сложнее и редко оправдан.
Распространённые причины ошибки
- Сохранение JSX-элементов в
localStorageилиsessionStorage. - Попытка рендерить объект, полученный из API, без преобразования в строку.
- Ошибочная передача объекта напрямую в JSX (например,
<div>{someObject}</div>).
Вывод
Ошибка Objects are not valid as a React child - следствие попытки рендерить несовместимый объект. В вашем случае достаточно хранить в localStorage только ключи или данные, а JSX-компоненты создавать динамически. Это сохранит работоспособность приложения и избавит от ошибок.