Redux:动作已成功调度,但未创建状态

Posted

技术标签:

【中文标题】Redux:动作已成功调度,但未创建状态【英文标题】:Redux: Action was successfully dispatched but the State was not created 【发布时间】:2021-04-16 01:01:46 【问题描述】:

我只是在制作一个简单的应用程序来学习 Redux。我使用 Redux DevTools 查看我的 2 个状态:liststodos。但是它只显示 todos,虽然我尝试了我所知道的一切,但它没有显示 lists

初始状态:

点击“添加”按钮后:

这是我的代码:

lists.js

import  createSlice  from "@reduxjs/toolkit";

const slice = createSlice(
  name: "lists",
  initialState: [],
  reducers: 
    listAdded: (lists, action) => 
      lists.push(
        id: action.payload.id,
        title: action.payload.title,
        todos: action.payload.todos,
      );
    ,
  ,
);

export const  listAdded  = slice.actions;
export default slice.reducer;

tod​​os.js

import  createSlice  from "@reduxjs/toolkit";

const slice = createSlice(
  name: "todos",
  initialState: [],
  reducers: 
    todoAdded: (todos, action) => 
      todos.push(
        id: action.payload.id,
        content: action.payload.content,
        check: action.payload.check
      );
    ,
    todoEdited: (todos, action) => 
      const index = todos.findIndex((todo) => todo.id === action.payload.id);
      todos[index].content = action.payload.content;
    
  
);

export const  todoAdded, todoEdited  = slice.actions;
export default slice.reducer;

reducer.js

import  combineReducers  from "redux";
import todosReducer from "./todos";
import listsReducer from "./lists";

export default combineReducers(
  lists: listsReducer,
  todos: todosReducer
);


configureStore.js

import  configureStore  from "@reduxjs/toolkit";
import reducer from "./reducer";

const store = () => 
  return configureStore( reducer );
;

export default store();

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./configureStore";
import  Provider  from "react-redux";

ReactDOM.render(
  <React.StrictMode>
    <Provider store=store>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

如您所见,它在我使用 dispatch 之后执行操作。但是,因为它没有 state,所以当我使用 lists.map 时,它会显示 'TypeError: Cannot read property 'map' of undefined'

请问我做错了什么?请帮忙!我很感激!

编辑:放更多与添加按钮相关的代码:

App.js

import React from "react";
import ItemTodo from "./ItemTodo";
import ItemList from "./ItemList";
import  useSelector  from "react-redux";
import NewListButton from "./NewListButton";
import NewTodoButton from "./NewTodoButton";

function App() 
  const todos = useSelector((state) => state.todos);
  const lists = useSelector((state) => state.lists);
  return (
    <div className="App">
      <div className="todo-list">
        <NewListButton />
        <div>
          lists.map((item) => (
            <ItemList key=item.id title=item.title />
          ))
        </div>
        <div>
          <h2>write a todo</h2>
          todos.map((item) => (
            <ItemTodo
              key=item.id
              id=item.id
              content=item.content
              check=item.check
            />
          ))
          <NewTodoButton />
        </div>
      </div>
    </div>
  );


export default App;

ItemList.js

import React from "react";

const ItemList = ( title ) => 
  return (
    <div className="list-item">
      <h2>title</h2>
      <div className="list-edit">edit name</div>
      <div className="list-remove">remove list</div>
    </div>
  );
;

export default ItemList;

ItemTodo.js


import React,  useState  from "react";
import  useDispatch  from "react-redux";
import  todoEdited  from "./todos";

const ItemTodo = ( id, content, check ) => 
  const dispatch = useDispatch();
  const [contentX, setContentX] = useState("");
  const inputTodo = (e) => 
    setContentX(e.target.value);
  ;
  const clickEdit = (e) => 
    e.preventDefault();
    dispatch(todoEdited( id, content: contentX ));
  ;
  return (
    <div>
      <form className="nav-submit">
        <input
          type="text"
          onClick=inputTodo
          onChange=inputTodo
          value=contentX
          onBlur=clickEdit
        />
      </form>
    </div>
  );
;

export default ItemTodo;

NewListButton.js

import  listAdded  from "./lists";
import  v4 as uuidv4  from "uuid";
import  useDispatch  from "react-redux";
import React,  useState  from "react";

const NewListButton = () => 
  const dispatch = useDispatch();
  const [titleX, setTitleX] = useState("");
  const getListTitle = (e) => 
    setTitleX(e.target.value);
  ;
  const setNewList = (e) => 
    e.preventDefault();
    const id = uuidv4();
    dispatch(listAdded( id, title: titleX, todos: [] ));
    setTitleX("");
  ;
  return (
    <div className="nav-list">
      <h2>write a list</h2>
      <form action="">
        <input type="text" onChange=getListTitle value=titleX />
        <button className="button-newlist" onClick=setNewList>
          New List
        </button>
      </form>
    </div>
  );
;

export default NewListButton;

NewTodoButton.js

import React from "react";
import  v4 as uuidv4  from "uuid";
import  useDispatch  from "react-redux";
import  todoAdded  from "./todos";

const NewTodoButton = () => 
  const id = uuidv4();
  const dispatch = useDispatch();
  const newTodo = (e) => 
    e.preventDefault();
    dispatch(todoAdded( id, content: "", check: true ));
  ;
  return (
    <div>
      <button className="button-new" onClick=newTodo>
        New Todo
      </button>
    </div>
  );
;

export default NewTodoButton;


编辑:更多信息。

这里有点奇怪:

我添加了一个文件:ListInitialState.js

const ListInitialState = [
  
    id: 1,
    title: "first list",
    todos: [],
  ,
];

export default ListInitialState;

然后将 ListInialState.js 导入 list.js:

import ListInitialState from "./ListInitialState";
import  createSlice  from "@reduxjs/toolkit";

const slice = createSlice(
  name: "lists",
  initialState: ListInitialState,
  reducers: 
    listAdded: (lists, action) => 
      lists.push(
        id: action.payload.id,
        title: action.payload.title,
        todos: action.payload.todos,
      );
    ,
  ,
);

export const  listAdded  = slice.actions;
export default slice.reducer;

终于成功了,但我不知道为什么:

如果有人解释它会很棒。我真的很感激!

【问题讨论】:

您的 listsReducer 是否有默认状态?你可以在问题中添加它吗? @Ashu 抱歉,这是什么意思?如何将其状态设置为默认值? 放一些添加按钮和触发reducer相关的代码? @Kalhan.Toress 抱歉,我认为这些代码足以获取状态。添加了更多代码。谢谢! 【参考方案1】:

可能你没有启用 redux 开发工具。

您可以使用此配置启用 redux 开发工具。

const store = configureStore(
  reducer,
  devTools: process.env.NODE_ENV !== 'production',
)

Redux DevTools Extension 已禁用生产

【讨论】:

您好,谢谢!我在 configureStore.js 中尝试了您的代码,然后“导出默认存储;”但它和以前一样吗? 他的 todo reducer 的状态正在显示,所以可能与 devtools 未连接有关 @Ashu 是的,问题是动作已经成功调度,但状态从未创建。 正如我之前提到的,你错过了初始状态,因此它直到你分派了动作才显示出来,redux 在开始时运行每个减速器,这些减速器返回一个初始状态,该状态存储在店铺。但我看到在 createSlice 你确实传递了一个空数组

以上是关于Redux:动作已成功调度,但未创建状态的主要内容,如果未能解决你的问题,请参考以下文章

Redux 状态不会随着动作调度而更新

在 react redux 中全局状态更改后调度新动作

在通过动作调度进行状态更新后,在 React 中使用 Redux 执行函数?

如何响应 redux 中的状态变化并派发另一个动作?

Next js 应用刷新时,useEffect 不调度 redux saga 动作并更新状态

如果异步操作已成功获取数据并更新状态,则也仅调度一次操作