简体   繁体   中英

My redux state is not updating when adding a new item via redux toolkit's addOne method with createEntityAdapter

I am trying to dispatch two thunks with entity adapters for adding to redux state, the first one works and the second one doesn't. I'm also not getting a payload in action.payload from the second dispatch. I suspect this is the issue but have no idea how to remedy it. Here is the code for it:

This one works fine:

export const addNewPost = createAsyncThunk(
  'posts/addNewPost',
  async (initialPost) => {
    const { text_body, is_helper, is_helped, active, owner_id, avatar, username, id} = initialPost

    const newPost = { 
      text_body, 
      is_helper, 
      is_helped, 
      active, 
      time_posted: new Date().toISOString(),
      avatar,
      owner_id,
      username,
      id
    }

    const response = await axios.post(url, newPost);
    return response.data
  }
)

const postsSlice = createSlice({
  name: 'posts',
  initialState,
  reducers: {
  },
  extraReducers: {
    [addNewPost.fulfilled]: (state, action) => {
      console.log(" payload: ", action.payload);
      postsAdapter.addOne(state, action.payload)
    },
  }
})

while this one does not:

export const addPostSkills = createAsyncThunk(
  'postSkills/addPostSkills',
  async (initialPostSkills) => {
    const {post_id, db_skills_id, id} = initialPostSkills
    console.log("initial post skills: ", initialPostSkills);
    const response = await axios.post(url, {post_id, db_skills_id, id});
    return response.data
  }
)

const postsSkillsSlice = createSlice({
  name: 'postsSkills',
  initialState,
  reducers: {
    // Tried something like this, it does not work
    postSkillAdded(state, action) {
      // console.log(state, action.payload);
      state.push(action.payload)
    }  
  },
    [addPostSkills.fulfilled]: (state, action) => {
      // console.log(state, action);
      // There is no payload showing up here.
      postsSkillsAdapter.addOne(state, action.payload)
    },
  }
})

And my dispatches are here:

  const OnSavePostClicked = async () => {

   const selectedSkill = JSON.parse(localStorage.getItem('selected_skill'));

    if (content === "") {
      setError("Post cannot be blank");
      return
    }
    if (selectedSkill === null) {
      setError("Please select a skill"); 
      return
    } else if (canSave) {

      id = postLength + 1;
      if (id !== null && id !== undefined) {
      try {
        setAddRequestStatus('pending')
        const postResultAction = await dispatch(
          addNewPost({ 
            id: id,
            owner_id: userId, 
            text_body: content,
            active: true, 
            is_helper: false, 
            is_helped: false, 
            avatar: loggedInUser.avatar,
            username: loggedInUser.username,
          })
        )
        unwrapResult(postResultAction)
        setContent('')
        setAddRequestStatus('pending')
        const postSkillResultAction = await dispatch(
          addPostSkills({ 
            id: uniquePostSkillId,
            post_id: id,
            db_skills_id: selectedSkill.id, 
            name: selectedSkill.name
          })
        )

          unwrapResult(postSkillResultAction)
        } catch (err) {
          console.error('Failed to save the post skill: ', err)
        } finally {
          setAddRequestStatus('idle')
          localStorage.setItem('selected_skill', null);
          setError("")
          wasSubmitted = true;
        }
      } 
    }
  }

Adding a new post will work in the backend and the front end state, adding a post skill will work in the backend fine and on refresh it shows, but nothing is passed to the redux state.

Thanks in advance for any help you can provide. Also sorry for the messiness, I'm sure I can and will clean it up a bit more once I Get it working!

Missing extraReducers

Your biggest issue is that the addPostSkills.fulfilled reducer is a top-level property of postsSkillsSlice . It needs to be inside of the extraReducers property.

const postsSkillsSlice = createSlice({
  name: 'postsSkills',
  initialState,
  reducers: {
    postSkillAdded: (state, action) => {
      state.push(action.payload)
    }  
  },
  extraReducers: {
    [addPostSkills.fulfilled]: (state, action) => {
      postsSkillsAdapter.addOne(state, action.payload)
    },
  }
});

Inconsistent State Shape

In your postSkillAdded reducer you call state.push , implying that state is an array . In your addPostSkills.fulfilled reducer, you pass state as an argument to postsSkillsAdapter.addOne , implying that state is an entity adapter (an object with properties ids and entities ). Which is it? These two cannot work together.

You might able to delete the postSkillAdded reducer if all adding is done through the thunk action. This looks a lot like your postsSlice , the one that works! The reducers property is empty and the thunk actions are handled in the extraReducers .

const postsSkillsAdapter = createEntityAdapter();

const initialState = postsSkillsAdapter.getInitialState();

const postsSkillsSlice = createSlice({
  name: 'postsSkills',
  initialState,
  reducers: {
  },
  extraReducers: {
    [addPostSkills.fulfilled]: (state, action) => {
      postsSkillsAdapter.addOne(state, action.payload)
    },
  }
});

Otherwise, make sure that all reducers rely on the same state shape.

const postsSkillsAdapter = createEntityAdapter();

const initialState = postsSkillsAdapter.getInitialState();

const postsSkillsSlice = createSlice({
  name: 'postsSkills',
  initialState,
  reducers: {
    postSkillAdded: (state, action) => {
      postsSkillsAdapter.addOne(state, action.payload)
    }  
  },
  extraReducers: {
    [addPostSkills.fulfilled]: (state, action) => {
      postsSkillsAdapter.addOne(state, action.payload)
    },
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM