Ошибка 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-компоненты создавать динамически. Это сохранит работоспособность приложения и избавит от ошибок.

    Часто задаваемые вопросы