保持Redux状态到本地存储

时间:2020-01-02 09:49:23

标签: arrays reactjs redux local-storage

我使用React创建了一个简单的应用程序。我试图使用本地存储来保持状态。但是,我添加的本地存储代码以某种方式阻止了我的组件完全呈现。不仅未显示待保存状态的待办事项,而且我的任何组件都不会渲染。刷新时出现空白页。有人可以帮助我找出问题所在吗?

这是包含本地存储代码后首次保存时发生的情况。它可以很好地加载组件,但是未显示已完成的待办事项:

enter image description here

使用表单添加到dos并刷新页面后,就会发生这种情况。没有显示任何组件。只是一个空白页。

enter image description here

这是我的index.js文件中的本地存储代码。我很确定问题出在这里,但我也包括了其他组件和化简器的代码:

const persistedState = localStorage.getItem('state') ? JSON.parse(localStorage.getItem('state')) : [];

const store = createStore(reducer, persistedState);

store.subscribe(() => {
    localStorage.setItem('state', JSON.stringify(store.getState()));
})

index.js文件的全文:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from "redux";
import { Provider } from "react-redux";
import './index.css';
import App from './App';
import { reducer } from "./reducers/todoReducer";
import * as serviceWorker from './serviceWorker';

const persistedState = localStorage.getItem('state') ? JSON.parse(localStorage.getItem('state')) : [];

const store = createStore(reducer, persistedState);

store.subscribe(() => {
    localStorage.setItem('state', JSON.stringify(store.getState()));
})

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>, 
    document.getElementById('root')
    );

其他组件: TodoList.js

import Todo from "./Todo";

const TodoList = props => {

    return (
        <ul className="task-list">
            {props.state.map(task => (
                <Todo task={task} />
            ))}
        </ul>
    )
}

const mapStateToProps = state => {
    return {
        state: state
    }
}

export default connect(mapStateToProps)(TodoList);

TodoForm.js

const TodoForm = props => {
    const [newItemText, setNewItemText] = useState("");

    const handleChanges = e => {
        e.preventDefault();
        setNewItemText(e.target.value);
      };

    const saveState = () => localStorage.setItem("props.state", JSON.stringify(props.state));

    useEffect(() => {
        const todos = localStorage.getItem('state');
        if (todos) props.setState({ [props.state]: JSON.parse(props.state) })
    }, [])

    return (
        <div className="form-div">
                <input
                    className="add-input"
                    name="todo"
                    type="text"
                    placeholder="enter a task"
                    value={newItemText}
                    onChange={handleChanges}
                />
                <button 
                    className="add-button"
                    onClick = {e => {
                    e.preventDefault();
                    props.addItem(newItemText);
                    saveState();
                    }}>Add a Task
                </button>
                <button 
                    className="add-button"
                    onClick={e => {
                    e.preventDefault();
                    props.removeCompleted();
                    }}>Remove Completed
                </button>
        </div>

    )
}

const mapStateToProps = state => {
    return {
        state: state
    } 
}

export default connect(mapStateToProps, {addItem, removeCompleted})(TodoForm);

Todo.js

const Todo = props => {

    return (
            <li 
                className="tasks"
                style={{textDecoration: props.task.completed ? 'line-through' : 'none'}} 
                onClick={() => props.toggleCompleted(props.task.id)}>
                    {props.task.item}
            </li>
    )
}

const mapStateToProps = state => {
    return {
        state: state
    }
}

export default connect(mapStateToProps, {toggleCompleted})(Todo);

todoReducer.js

export const initialState = [
    { item: 'Learn about reducers', completed: false, id: 1 },
    { item: 'review material from last week', completed: false, id: 2 },
    { item: 'complete reducer todo project', completed: false, id: 3 }
]

export const reducer = (state = initialState, action) => {
    switch(action.type) {
        case ADD_ITEM:
            // console.log(action.payload)
            return [
                ...state,
                {
                    item: action.payload,
                    completed: false,
                    id: Date.now()
                }
            ]
        case TOGGLE_COMPLETED:
            const toggledState = [...state];
            toggledState.map(item => {
                if(item.id === action.payload) {
                    item.completed = !item.completed;
                }
            })
            console.log(toggledState);
            state = toggledState;
            return state;

        case REMOVE_COMPLETED:
           return state.filter(item => !item.completed);
        default:
            return state;
    }
}

export default reducer;

App.js

import React from 'react';
import './App.css';

// components
import TodoList from "./components/TodoList";
import TodoForm from "./components/TodoForm";

function App() {

  return (
    <div className="App">
        <h1 className="title">To Do List</h1>
        <TodoList />
        <TodoForm />
    </div>
  );
}

export default App;

actions.js

export const ADD_ITEM = 'ADD_ITEM';
export const TOGGLE_COMPLETED = 'TOGGLE_COMPLETED';
export const REMOVE_COMPLETED = 'REMOVE_COMPLETED';

export const addItem = input => {
    return { 
        type: ADD_ITEM, payload: input
    }
  };

export const toggleCompleted = (id) => {
    return { 
        type: TOGGLE_COMPLETED, payload: id 
    }
  };

export const removeCompleted = () => {
    return { 
        type: REMOVE_COMPLETED 
    }
  };

0 个答案:

没有答案