Search code examples
redux-toolkit

override object properties in createAsyncThunk method


I have a function like this

export const fetchChildrenNews = createAsyncThunk('news/fetch1', async ([item, news]) => {
      const res = await Promise.all(item.kids.map(id => {
        let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`;
        return fetch(url);
      }));
      const jsons = await Promise.all(res.map(r => r.json()));
      let users = {...item, kids: jsons};
      item.kids = []//doesn't work
      item.id = 0 //doesn't work

      //I want to find a branch in the original tree and replace it

      const tree = (obj) => {
          for (let key in obj) {
              if (key === "id" && obj[key] === users.id) {
                obj = users;
              }

              if (key == "kids") {
                tree(obj);
              }
          }
      }

      tree(item);

where item is a nested object record: {by: 'nullzzz', descendants: 47, id: 28808556, kids: Array(13), score: 117}. kids property contains array of ids and in the users variable it becomes an array of records. and my goal change record.kids = [0, 7, 14] to record.kids = users ([{by: '...', id:4848,..], [{by: 'adasd'], [{by: 'zzz}] ). the variable news is a whole tree while item its branches. I just started working with the toolkit, so I don't fully understand this


Solution

  • Since item is probably an object from your Redux store, that thunk would try to modify a reference to your store - and modifying the store is only allowed in reducers.

    Generally, you should be doing logic like this in reducers, not in a thunk.

    So, do

    export const fetchChildrenNews = createAsyncThunk('news/fetch1', async ([item, news]) => {
          const res = await Promise.all(item.kids.map(id => {
            let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`;
            return fetch(url);
          }));
          const jsons = await Promise.all(res.map(r => r.json()));
          return jsons
    })
    

    and then in your slice, add the logic:

    builder.addCase(fetchChildrenNews, (state, action) => {
      const jsons = action.payload
    
      // here, do not modify `items`, but modify `state` - I would assume `items` is somewhere in here anyways?
    })