localStorage обновляется со значением начального состояния при обновлении - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь использовать localStorage для сохранения состояния компонента на refre sh. Компонент отлично работает при первоначальном рендеринге страницы, но он не работает с сообщением: TypeError: items.map не является функцией

TestLocalStorage
src/TestLocalStorage.jsx:54

Вот код:

import React, { useEffect, useState } from 'react';

function TestLocalStorage() {
    const [items, setItems] = useState([]);

    useEffect(() => {
        const storedData = localStorage.getItem("items");
        if(!storedData) {
            Axios.get('/url').then(response => {
                const serviceResponse = response.data.hits.map(obj=> ({ ...obj, voteCount: 0 
           }));
                localStorage.setItem("items", JSON.stringify(serviceResponse));
                setItems(serviceResponse);
            });
        } else {
            setItems(storedData);
        }
    }, []);

    useEffect(() => {
        localStorage.setItem("items", JSON.stringify(items));
    })

    function increment(id) {
        const elementsIndex = items.findIndex(element => element.objectID === id )
        items[elementsIndex].voteCount++;
        setItems([...items]);
    }

    return (
        <table cellPadding="0" cellSpacing="0" width="100%" background-color="#f6f6ef">
         <tr>
            <td>
               <table border="0" cellPadding="0" cellSpacing="0" width="100%">
                    <tr bgcolor="#ff6600" style={{ color:"white", fontWeight: "bold" }}>
                        <td> Comments </td>
                        <td> Vote Count</td>
                        <td> vote</td>
                    </tr>
                    {
                        items.map((item) => {
                            return (
                            <tr className="table-rows" key={item.objectID}>
                                <td>{ item.comments }</td>
                                <td>{ item.voteCount }</td>
                                <td>
                                    <div 
                                        style={{ 
                                            width: 0, 
                                            height: 0, 
                                            borderTop: 0, 
                                            borderLeft: "5px solid transparent", 
                                            borderRight: "5px solid transparent", 
                                            borderBottom: "10px solid grey" 
                                        }}
                                        onClick={() => increment(item.objectID)} 
                                    />
                                </td>
                                <td>{ item.title }</td>
                            </tr>)
                        })
                    }
               </table>
            </td>
         </tr>
      </table>
    );
}
export default TestLocalStorage;

Но я заметил, что при втором рендеринге localStorage имеет начальное значение [], установленное вместо недавно обновленного. Не уверен, где я ошибаюсь. Пожалуйста, помогите

Ответы [ 2 ]

2 голосов
/ 11 июля 2020

Выполните синтаксический анализ строки, которую вы извлекаете из локального хранилища, используя JSON .parse ()

function TestLocalStorage() {

        const [items, setItems] = useState([]);
    
        useEffect(() => {
            const storedData = localStorage.getItem("items");
            if(!storedData) {
                Axios.get('/url').then(response => {
                    const serviceResponse = response.data.hits.map(obj=> ({ ...obj, voteCount: 0 
               }));
                    localStorage.setItem("items", JSON.stringify(serviceResponse));
                    setItems(serviceResponse);
                });
            } else {
                setItems(storedData);
            }
        }, []);

        ...............
        ...............
        ...............

}

Измените свою функцию, как показано ниже. Кроме того, проверьте значение элементов перед выполнением операции сопоставления с массивом, чтобы предотвратить неперехваченные исключения

function TestLocalStorage() {

        const [items, setItems] = useState([]);
    
        useEffect(() => {
            const storedData = JSON.parse(localStorage.getItem("items"));
            if(!storedData) {
                Axios.get('/url').then(response => {
                    const serviceResponse = response.data.hits.map(obj=> ({ ...obj, voteCount: 0 
               }));
                    localStorage.setItem("items", JSON.stringify(serviceResponse));
                    setItems(serviceResponse);
                });
            } else {
                setItems(storedData);
            }
        }, []);

        ...............
        ...............
        ...............
        return (
           .....
           .....
           items && items.map((item) => {
           .....
           .....
        )
}
2 голосов
/ 11 июля 2020

storedData будет строкой, вам нужно JSON.parse(storedData), чтобы использовать это и сделать map на нем

...