我怎样才能坚持 redux 状态

How can I persist redux state

我正在开发一个 CRUD,在其中一个组件中,当用户创建 post 时,div 会使用他的 [=29= 的标题和内容值呈现].即使他在页面之间导航(不刷新页面),我也需要保存他的 posts。目前,我可以根据需要创建任意数量的 post,它们会一个接一个地排列,但是当我返回上一页时,它们会被删除。我试图在这部分实现 redux,就像我实现它以保存用户输入(创建一个切片来保存 posts)一样,但它没有用。我知道通常 posts 不会被删除,所以我想知道我哪里出错了。

注册屏幕:

import React, {useState, useEffect} from "react";
import "../_assets/signup.css";
import "../_assets/App.css";
import { useDispatch } from 'react-redux';
import userSlice from '../redux/userslice';
import { useNavigate } from "react-router-dom";



    function Signup() {
    
      const navigate = useNavigate();
    
      const dispatch = useDispatch();
    
      const [name, setName] = useState('')
    
      const [buttonGrey, setButtonGrey] = useState('#cccccc')
    
    
    
      useEffect(() => {
    
    
          if (name!== '') {
              
              setButtonGrey("black")
          }  
    
          else {
            setButtonGrey('#cccccc')
            
          }
      }, [name])
    
      
    
      const handleSubmitForm= (e) => {
        e.preventDefault()
        dispatch(userSlice.actions.saveUser(name))
        navigate("/main")
       
    
      }
    
      const handleChangeName = (text) => {
        setName(text)
      }
    
      return (
        <div className="container">
          <div className="LoginBox">
          <form onSubmit={handleSubmitForm}>
            <h2>Welcome to codeleap network</h2>
            <text>Please enter your username</text>
            <input type="text" name="name" value={name} onChange = {e => handleChangeName(e.target.value)}  placeholder="Jane Doe"  />
            <div className="button">
            <button type="submit" style={{backgroundColor: buttonGrey}}  disabled={!name} >
              ENTER
            </button>
    
            </div>
            </form>
          </div>
        </div>
      );
    }
    
    export default Signup;

CRUD 屏幕:

import React, { useState, useEffect } from "react";
import "../_assets/App.css";
import "../_assets/mainscreen.css";
import { MdDeleteForever } from "react-icons/md";
import { FiEdit } from "react-icons/fi";
import { useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import { Navigate } from 'react-router-dom';
import postsSlice from '../redux/postsslice'

import Modal from "../components/modal.jsx";

function MainScreen() {

  const dispatch = useDispatch();

  const user = useSelector((state) => state.user)
  const loadPosts = useSelector((state) => state.loadPosts)

  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const [newPosts, setNewPosts] = useState([])
  const [buttonGreyOut, setButtonGreyOut] = useState("#cccccc");

  useEffect(() => {
    if (title && content !== "") {
      setButtonGreyOut("black");
    } else {
      setButtonGreyOut("#cccccc");
    }
  },[title, content]);



  const handleSubmitSendPost = (e) => {
    e.preventDefault();
    setNewPosts(newPosts.concat({title, content}))
    dispatch(postsSlice.actions.savePosts(newPosts))
    setTitle('')
    setContent('')
  };

  const handleChangeTitle = (text) => {
    setTitle(text);
  };

  const handleChangeContent = (text) => {
    setContent(text);
  };


  const [openModal, setOpenModal] = useState();

  if (user === '') {
    return <Navigate to="/" />
  } else {
    return (
      <div className="containerMainScreen">
        {openModal && <Modal closeModal={setOpenModal} />}
        <div className="bar">
          <h1>Codeleap</h1>
        </div>
        <div className="boxPost">
          <h2 style={{ fontWeight: 700 }}>What's on your mind?</h2>
          <h2>Title</h2>
          <form onSubmit={handleSubmitSendPost}>
            <input
              type="text"
              placeholder="Hello World"
              name="name"
              value={title}
              onChange={(e) => handleChangeTitle(e.target.value)}
            ></input>
            <h2>Content</h2>
            <textarea
              placeholder="Content"
              name="content"
              value={content}
              onChange={(e) => handleChangeContent(e.target.value)}
            ></textarea>
            <button
              className="createButton"
              type="submit"
              style={{ backgroundColor: buttonGreyOut }}
              disabled={!title || !content}
            >
              CREATE
            </button>
          </form>
        </div>
  
        {newPosts.map((post) => (
          <div className="boxPost">
            <div className="bar">
              <h1>{post.title}</h1>
              <MdDeleteForever
                className="icon"
                onClick={() => {
                  setOpenModal(true);
                }}
              />
              <FiEdit
                style={{ color: "white", fontSize: "45px", paddingLeft: "23px" }}
              />
            </div>
            <div id="postowner">
              <h3>@{user}</h3>
            
             
              <h3>25 minutes ago</h3>
              <br></br>
              <textarea style={{ border: "none" }}>{post.content}</textarea>
            </div>
          </div>
        ))}
      </div>
    );
  }
  
  
  }export default MainScreen;

store.js:

import { configureStore } from '@reduxjs/toolkit';
import userSlice from './userslice';
import postsSlice from './postsslice'

export const store = configureStore({
  reducer: {
      user: userSlice.reducer,
      loadPosts: postsSlice.reducer
  },
})

post切片:

import { createSlice } from "@reduxjs/toolkit";

const postsSlice = createSlice({
  name: "posts",
  initialState: "",
  reducers: {
    savePosts: (state, action) => action.payload
  }
});

export default postsSlice

增删改查截图: https://i.stack.imgur.com/YoCJz.png

您正在调度 savePosts 操作,其值为 newPosts,当前 post 添加到其中之前。问题出在这些行中:

setNewPosts(newPosts.concat({title, content}))
dispatch(postsSlice.actions.savePosts(newPosts))

试试这样的方法:

const posts = newPosts.concat({title, content})
setNewPosts(posts)
dispatch(postsSlice.actions.savePosts(posts))

将posts 数组存储在Redux 中并同时存储在本地组件状态中是没有意义的。在我看来,你应该放弃组件 newPosts 状态并通过 Redux 使用 useSelector.

访问 posts

我还建议调度 addPost 操作,它只需要当前 post。让 reducer 处理将它添加到数组中。

状态是一个 post 数组,所以你的 initialState 应该是一个空数组而不是一个空字符串。

const postsSlice = createSlice({
  name: "posts",
  initialState: [],
  reducers: {
    // add one post to the array.
    addPost: (state, action) => {
      state.push(action.payload); // modifies the draft state.
    },
    // replace the entire array.
    replacePosts: (state, action) => action.payload
  }
});
function MainScreen() {

  const dispatch = useDispatch();

  const user = useSelector((state) => state.user)
  const posts = useSelector((state) => state.loadPosts)

  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  
  /* ... */

  const handleSubmitSendPost = (e) => {
    e.preventDefault();
    dispatch(postsSlice.actions.addPost({title, content}))
    setTitle('')
    setContent('')
  };