如何在ReactJS中使用LocalStorage更新状态

时间:2019-08-14 08:37:41

标签: javascript reactjs local-storage

我有一个数组,每次调用componentDidMount()时都会提取API数据。我有一个默认值为true的对象,该对象推入数组中的每个元素。设置了onClick函数,以便在单击特定元素时,其布尔值将更改为false并将该数组放置在localStorage中。

我需要数据数组在每次重新加载页面时不断刷新,因此我在我的componentDidMount()方法中进行了检查,该方法仅从刚保存在localStorage中的数组接收布尔值。

尽管这可行,但布尔值是根据索引而不是元素本身分配的。这里的问题是,如果位置2的元素“ A”最初设置为false,然后在另一个API调用之后与位置3的元素“ B”交换,则布尔值将不正确,因为现在的“ B”为假,“ A”现在为真。

import React from 'react';
import StarBorder from '@material-ui/icons/StarBorder';
import Star from '@material-ui/icons/Star';
import axios from 'axios';

class Test extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          data: [],
        }
    }

    componentDidMount() {

            axios.get('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=true')
            .then(res => {
                const data = res.data;

                const fromLocalStorage = localStorage.getItem('test');

                if (localStorage.getItem('test')) {
                  const dataFromLocalStorage = JSON.parse(fromLocalStorage);
                  this.setState({ data: data.map((x, i) => ({...x, starIcon: dataFromLocalStorage[i].starIcon }))})
                } else {
                 this.setState({ data: data.map(x => ({...x, starIcon: true}))})
                }

            }) 
    }

    handleClick = (n) => {

        this.setState(prevState => ({
          data: prevState.data.map((x) => (x === n ? {
            ...x,
            starIcon: !x.starIcon
          } : x))
        })
        , () => {
          localStorage.setItem('test', JSON.stringify(this.state.data));
        });

      }

    render() {
        return (
        <div>
            <table border="1">
                <thead>
                    <tr>
                    <td>Rank</td>
                    <td>Icon</td>
                    <td>Name</td>
                    <td>Price</td>
                    </tr>
                </thead>
                <tbody>
                {this.state.data.map((n, i) => {
                    return (
                        <tr>
                        <td>{n.market_cap_rank}</td>
                        <td> <span onClick={() => this.handleClick(n)}> {n.starIcon ? <StarBorder/> : <Star /> } </span> </td>
                        <td>{n.name}</td>
                        <td>{n.current_price}</td>
                        </tr>
                    );
                    })}
                </tbody>
            </table>
        </div>
        );
    }
}

export default Test;

Codesandbox链接https://codesandbox.io/s/shy-fog-7yplb

如果要更改位置40上名为“ Algorand”的示例项目,请单击true到false来按预期工作。但是,API调用将刷新其余数据,并且“ Algorand”可能不再位于位置40,但是位置40的布尔值仍然为false,并且未映射到“ Algorand”

1 个答案:

答案 0 :(得分:1)

尝试在您的componentDidMount中使用它

class MyProgramLauncher {public static void main(String[] args) {MyProgram.main(args);}}

我要做的是在您映射状态下的刷新数据时,我没有从整个对象中匹配(这将无法正常工作),而是从数组中找到了正确的对象,并从其中使用了startIcon。