首页 > 解决方案 > 如何在 ToDo App 中渲染本地存储中的每个项目

问题描述

如何渲染本地存储中的所有项目并在每次渲染后将它们显示为反应组件?我正在尝试制作一个 toDo 应用程序,我试图将用户键入的数据缓存到复选框中。

每当用户离开页面并返回时,他们之前在复选框中键入的数据仍会显示。我已经部分解决了这个问题,但我在这里遇到的问题是无法将本地存储中的所有项目显示为 useEffect 中的反应组件。有什么好的解决方案可以解决这个问题?

**Tasks.JSX**
    import React, {useState, useEffect} from "react";
    import {Delete, Refresh, Add} from "../components/Actions";
    import {Header} from "../components/Header";
    import {PriorityLists} from "../components/PriorityLists";
    import {v4 as uuidv4} from 'uuid';
    import { serialize, deserialize } from "react-serialize";
    
    

    function Task() {
       
    
      
        const [toDo, setToDo] = useState([])
        const [idsToRefresh, setIdsToRefresh] = useState([]);
        const [filter_items, setFilterItems] = useState(false);
        const [ids, setIds] = useState([]);
       
        const [text, setTextValue] = useState({key:null, txt:null});
    
        useEffect(()=> {
            for(let i=0; i < localStorage.length; i++) {
                let storedValue = localStorage.key(i);
                let value = JSON.parse(localStorage.getItem(storedValue));
                if(typeof value === "string") {
                    setToDo(toDo.concat({_Id: storedValue, item_value: <PriorityLists id = {storedValue} checked = {false} addIds = {addIds} local_storage ={ls} text_value = {value} />}));
                    console.log(`${value} Index ${i}`);
                }
                    
                
                
               
            }
        }, [])
    
    
    
        
        useEffect(() => {
            if(toDo[0] !== undefined) {
                setToDo(toDo.filter(item=> {
                    return !ids.includes(item._Id);
                }))
               
            }
    
    
        }, [filter_items]);
    
        function addIds(checked, id_to_be_deleted) {
            if(!checked) {
                setIds((item)=> [...item, id_to_be_deleted]);
            }
            else {
                setIds(ids.filter(item=> {
                    return item !== id_to_be_deleted;
                }))
            }
        }
        
        function ls(e) {
            localStorage.setItem(JSON.stringify(e.target.id), serialize(e.target.value));
            
        }
    
        
    
    
    
        function addToDos() {
            const id = uuidv4();
         
            setToDo(toDo.concat({_Id: id, item_value: <PriorityLists id = {id} checked = {false} addIds = {addIds} local_storage ={ls} text_value = {null} />}));
            setIdsToRefresh(idsToRefresh.concat(id));
       
        }
    
      
        
    
        function refresh() {
            setToDo(toDo.filter(item=> {
                return !idsToRefresh.includes(item._Id);
            }))
        }
    
    
    
        return (
        <div className = "main-content">
            <div className = "container-fluid">
                <div className = "row underline">
                    <div className= "col">
                        <div className = "row">
                        <div className = "col-3 pt-2">
                            <Refresh _refresh = {refresh} />
                        </div>
    
                        <div className = "col-6 text-center">
                            <Header header ={"Tasks"}/>
                        </div>
    
                        <div className = "col-3 pt-2">
                            <button  className = "float-right">
                                <Delete setFilterItems = {setFilterItems} filter = {filter_items} />
                            </button>
                        </div>
    
                        </div>
                    </div>
                </div>
    
                <div className = "row">
                    <div className = "col">
              
                       {
                       
                       
                       toDo.map(item=> {
                           return (<div key = {item._Id}> 
                           <ul>
                               <li>{item.item_value}</li>
                             
                           </ul>
                           </div>)
                       })}
                        
                       
     
                        
                    </div>
                </div>
    
    
                <div className = "row">
                    
                    <div className = "col pr-4">
            
                        <Add addToDos = {addToDos} />
                    
                    </div>
                </div>
    
    
    
            
            </div>
        </div>
        
        )
    }
    
    export default Task;

PriorityLists.jsx

import React, {useState, useEffect} from "react";
import { Priority } from "./Actions";




function PriorityLists(props) {
    const [isChecked, setChecked] = useState(false);
    const [changeInput, setChangeInput] = useState(props.text_value);



    function check(e) {
        const id_to_be_deleted = e.target.attributes.getNamedItem("unique_Key").value;
       
        if(!isChecked) {
            setChecked(true);
            props.addIds(isChecked, id_to_be_deleted);

        }

        else {
            setChecked(false);
            props.addIds(isChecked, id_to_be_deleted)
        }
    }

    function setChange(e) {
        setChangeInput(e.target.value);
        props.local_storage(e);
    }

    

    return ( 
    <form key = {props.id}  >
       <div className = "input-group mb-3">
            <div className="input-group-prepend">
                <div className="input-group-text">
                <input unique_Key = {props.id}   onInput = {e=>   e.target.checked = isChecked} onClick={e=> check(e) } checked = {props.checked} id = "check-item" type="checkbox" aria-label="Checkbox for following text input"/>
                </div>
            </div>
            <textarea id = {props.id} onChange = {e=>setChange(e)} value = {changeInput}   class="form-control"  rows="1" name = {props.name}></textarea>
            <Priority id = {props.id} text_value = {changeInput} />
         </div>
   </form>
    )
}

export {PriorityLists};

标签: reactjslocal-storage

解决方案


一种方法是向存储事件添加事件侦听器,该事件侦听器每次都会触发函数调用。

Vo 提到了一种处理存储事件的方法。

如果您从初始挂载的存储中加载数据,并将其存储在跨组件共享的上下文中,我个人会更喜欢。

通过这种方式,您可以直接更新状态,并且作为副作用,您也可以更新 localStorage。

在我看来,这是一种更清洁的方法。

  • saveData loadData在 localStorage 的 utils 函数中创建
  • 使用 key 加载数据,并在 AppContext 中存储为 initState
  • 跨视图共享状态。
  • 更新状态
  • 添加带有状态的 useEffect,并在状态更新时保存数据

我希望这能解决你的问题


推荐阅读