Как использовать window.onload в React?
Изучаю react. Хочу вывести комментарии, хранящиеся в localStorage при загрузке страницы, но не соображу, как это сделать. Пробовал скопировать массив из состояния и закинуть в него всё, что есть в сторожке так:
window.onload = function() {
const initialItems = [...items]
for (let i = 0; i < localStorage.length; i++) {
initialItems.push(JSON.parse(localStorage.getItem(items.itemId)));
}
setItems(items);
};
Код компонента:
import CommentForm from './CommentForm'
import CommentList from './CommentList'
import CommentatorsTop from "./CommentatorsTop";
import {useState} from 'react';
function CommentWidget() {
const [items, setItems] = useState([]);
window.onload = function() {
const initialItems = [...items]
for (let i = 0; i < localStorage.length; i++) {
initialItems.push(JSON.parse(localStorage.getItem(items.itemId)));
}
setItems(items);
};
function addItem(item) {
const newItems = [...items]
newItems.push(item)
setItems(newItems);
const storageNewItems = JSON.stringify(newItems);
localStorage.setItem(item.itemId, storageNewItems);
}
function removeCommentItem(position, itemId) {
if (window.confirm('Удалить?')) {
const newListItem = [...items]
newListItem.splice(position, 1);
localStorage.removeItem(itemId);
setItems(newListItem);
}
}
return (
<div className="CommentWidget">
<div className="CommentForm-wrap">
<CommentForm addNewItem={addItem}/>
<CommentList comments={items} removeCommentItem={removeCommentItem} />
</div>
<CommentatorsTop names={items}/>
</div>
)
}
export default CommentWidget;
Что я тут делаю не так?
Ответы (2 шт):
https://ru.reactjs.org/docs/hooks-effect.html Вам нужен хук UseEffect. Он отслеживает перерендеринг компонента и вызывает функцию, которая выполняется, когда компонент рендерится. Если у этой функции будет return, то во время уничтожения компонента выполнится код из этого return.
Так вот, первым параметром UseEffet принимает функцию, вторым - массив зависимостей. Если второй параметр не будет передан, то функция переданная UseEffect будет вызываться при каждом перерендеринге. Если в качестве параметра будет передан пустой массив, то функция отработает лишь один раз, при первом рендеринге компонента. В качестве элемента этого массива может быть какое-нибудь состояние, например, или любая другая зависимость. Суть в том, что когда это, например, состояние будет изменено, тогда вызовится функция из UseEffect. Аналагом window.onload будет UseEffect со вторым параметром пустым массивов (выполнить при первом рендеринге компонента). Замените блок с
window.onload = function() {
на что-то следующее
import React, { useState, useEffect } from 'react';
......
useEffect(() => {
const initialItems = [...items]
for (let i = 0; i < localStorage.length; i++) {
initialItems.push(JSON.parse(localStorage.getItem(items.itemId)));
}
setItems(items);
}, []);
Нашёл ошибку в функции addItem: отправлять в localStorage здесь следует элемент item, а не массив, конечно.
Однозначно, здесь можно использовать, хук useEffect. Однако, поскольку вопрос касался именно window.onload оставлю здесь решение. При перезагрузке страницы копировать массив items не нужно и бессмысленно. Необходимо объявить пустой массив
const storageItems = []и добавить в него всё, что есть в localStorage так:for (let i = 0; i < localStorage.length; i++) { storageItems.push(JSON.parse(localStorage.getItem(localStorage.key(i)))); }и затем передать массив в state:setItems(items);
В итоге компонент выглядит так:
import CommentForm from './CommentForm'
import CommentList from './CommentList'
import CommentatorsTop from "./CommentatorsTop";
import React, {useState} from 'react';
function CommentWidget() {
const [items, setItems] = useState([]);
window.onload = function () {
const storageItems = []
for (let i = 0; i < localStorage.length; i++) {
storageItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
}
setItems(storageItems);
};
function addItem(item) {
const newItems = [...items]
newItems.push(item)
setItems(newItems);
const storageNewItems = JSON.stringify(item);
localStorage.setItem(item.itemId, storageNewItems);
}
function removeCommentItem(position, itemId) {
if (window.confirm('Удалить?')) {
const newListItem = [...items]
newListItem.splice(position, 1);
localStorage.removeItem(itemId);
setItems(newListItem);
}
}
return (
<div className="CommentWidget">
<div className="CommentForm-wrap">
<CommentForm addNewItem={addItem}/>
<CommentList comments={items} removeCommentItem={removeCommentItem}/>
</div>
<CommentatorsTop names={items}/>
</div>
)
}
export default CommentWidget;