Search code examples
reactjsreduxreact-reduxreact-hooksredux-thunk

useSelector hooks problem after submitting data


I'm not sure if the problem is in useSelector or in useDispatch hooks or in another place, so here is the scenario:

  • Two screens (HomeScreen & AddBlogScreen)
  • In HomeScreen I click add blog button then it redirect to AddBlogScreen
  • I input the data, then submit. After the submit is success then redirect to HomeScreen
  • As mentioned in below pic, I got the no 4 result & I have to refresh to get the no 3 result. But my expectation is no 3 pic without getting the error.

enter image description here

Here is my code:

HomeScreen

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>
 );
};

actions

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,
  });
 }
};

reducer

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;
     }
    };

store

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);

Solution

  • I found the solution, so in my action I changed it into:

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