提交数据后useSelector hooks问题

useSelector hooks problem after submitting data

我不确定问题是在 useSelector 还是在 useDispatch 钩子或其他地方,所以情况是这样的:

这是我的代码:

主屏幕

import jwtDecode from "jwt-decode";
import React, { useEffect, useState } from "react"; 
import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router";
import { blogList } from "../redux/action";

export const MainScreen = () => {
// const [token, setToken] = useState(localStorage.getItem("token"));
 const user = jwtDecode(localStorage.getItem("token"));
 const history = useHistory();
 const dispatch = useDispatch();
 useEffect(() => {
   dispatch(blogList());
 }, [dispatch]);

 const { blog } = useSelector((state) => state.blog);
 console.log(blog);

 return (
<>
  <button
    onClick={() => {
      localStorage.removeItem("token");
      history.push("/");
    }}
  >
    singout
  </button>
  <button
    onClick={() => {
      history.push({ pathname: "/Blog", state: user });
    }}
  >
    add blog
  </button>
  <h1 style={{ color: "red" }}>username: {user.username}</h1>
  {blog.map(({ id, b_title, b_content, category_id }) => (
    <div key={id}>
      <h1
        onClick={() =>
          history.push({
            pathname: "/Edit",
            state: { id, b_title, b_content, category_id },
          })
        }
      >
        Title: {b_title}
      </h1>
      <p>Content: {b_content}</p>
    </div>
  ))}
</>
);
};

AddBlogScreen

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useHistory, useLocation } from "react-router";
import { addBlog } from "../redux/action";

export const AddBlogScreen = () => {
  const history = useHistory();
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");
  const [category, setCategory] = useState("");

  const dispatch = useDispatch();

  const location = useLocation();
  const author = location.state.id;


  const submitHandler = (e) => {
    e.preventDefault();

    dispatch(addBlog(title, content, author, category));
    setTitle("");
    setContent("");
    setCategory("");
    history.push("/Home");

 };

return (
<div>
  <h1>add blog page</h1>
  <form onSubmit={submitHandler}>
    <input
      type="text"
      placeholder="title"
      value={title}
      onChange={(e) => setTitle(e.target.value)}
    />
    <br />
    <br />
    <input
      type="text"
      placeholder="content"
      value={content}
      onChange={(e) => setContent(e.target.value)}
    />
    <br />
    <br />
    <input
      type="text"
      placeholder="category"
      value={category}
      onChange={(e) => setCategory(e.target.value)}
    />
    <br />
    <br />
    <input
      type="submit"
      value="submit"
      disabled={
        title === "" || content === "" || category === "" ? true : false
      }
    />
  </form>
</div>
 );
};

动作

import axios from "axios";
import {
 LIST_BLOG,
 ADD_BLOG,
 EDIT_BLOG,
 DELETE_BLOG,
 LOGIN_USER,
 REGISTER_USER,
 LOGOUT_USER,
} from "./constant";

// ==================== blog actions ======================
export const blogList = () => async (dispatch) => {
try {
  const result = await axios
  .get("http://localhost:3001/api/v1/blog?page=0")
  .then((res) => res.data.data)
  .catch((err) => err);

dispatch({
  type: LIST_BLOG,
  payload: result,
});
} catch (err) {
dispatch({
  payload: err,
});
 }
};

export const addBlog =
 (title, content, author, category) => async (dispatch) => {
   try {
    const result = await axios
    .post("http://localhost:3001/api/v1/blog", {
      blog_title: title,
      blog_content: content,
      author_id: author,
      category_id: category,
    })
    .then(alert("success add blog"))
    .catch((err) => alert(err));

  dispatch({
    type: ADD_BLOG,
    payload: result,
  });
} catch (err) {
  dispatch({
    payload: err,
  });
 }
};

减速机

const initial_state = {
 blog: [],
 };

export const blogReducer = (state = initial_state, action) => {
  switch (action.type) {
    case LIST_BLOG:
      return {
        ...state,
        blog: action.payload,
    };
    case ADD_BLOG:
      return {
        ...state,
        blog: action.payload,
     };
    case EDIT_BLOG:
     return {
       ...state,
       blog: action.payload,
     };
    case DELETE_BLOG:
     return {
       ...state,
       blog: action.payload,
     };
     default:
      return state;
     }
    };

商店

import { blogReducer, userReducer } from "./reducer";
import { combineReducers, createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";

const reducer = combineReducers({
   blog: blogReducer,
   user: userReducer,
 });
const middleWare = composeWithDevTools(applyMiddleware(thunk));

export const store = createStore(reducer, middleWare);

首先错误的来源:

错误说 blog 上名为 map 的 属性 不是函数,意思是 blog 不是数组。

这是它的来源:

 const { blog } = useSelector((state) => state.blog);

您的状态是一个带有 属性 命名博客的对象,您可以通过以下两种方式访问​​它:

 const { blog } = useSelector((state) => state);

 const blog = useSelector((state) => state.blog);

我注意到的其他问题:

addBlog中:

1. 当您将 try-catchawait 一起使用时,最好也使用 then-catch

2.result 不会是您期望的博客数据。它将是一个对象,它是 AxiosResponse 的一个实例,其中包含数据。 您可以通过这种方式从 response 对象中提取 data

let response = await axios.post(... // some api request
let {data}=response

我会这样编辑:

    export const addBlog =
 (title, content, author, category) => async (dispatch) => {
   try {
    const {data} = await axios
    .post("http://localhost:3001/api/v1/blog", {
      blog_title: title,
      blog_content: content,
      author_id: author,
      category_id: category,
    })

  alert("success add blog")
  dispatch({
    type: ADD_BLOG,
    payload: data,
  });
} catch (err) {
  dispatch({
    payload: err,
  });
 }
};

我找到了解决方案,所以在我的操作中我将其更改为:

dispatch({
  type: LIST_BLOG,
  payload: result.data.data,
 });