Antfere
Antfere

Reputation: 90

Return statement in async function of redux item reducer not changing state

I am trying to use redux to change my react state. My other action cases seem to work well but I am stuck on this one. I think the root of the problem is the async function but I am unsure. I simply cannot change the state with the return statement in the async function. My best guess is that the return statement only works on same scope as the "if" statement and as such I cant return from inside the async function to change the state. If this is the reason how can I take a value from an async function and move it up one level in the state to return it? If the problem has nothing to do with the scope then I am all ears aswell.

itemReducer.js:

case ADD_ITEM:

    if (action.payload.match(/soundcloud.com/) == "soundcloud.com") {

        // First async await
        async function newItem() {

            console.log("0")
            const response = await fetch("https://soundcloud.com/oembed?format=json&url=" + action.payload );
            const json = await response.json();

            let html = json.html.match(/(?<=url=).{53}/).toString()

            let newItem = {
                id: uuidv4(),
                url: html,
                name: json.title,
                isOpen: false
            }

            console.log(newItem, ...state.items)

            return {
                items: [...state.items, newItem]
            }

        }

        newItem();
    
    }

Upvotes: 0

Views: 853

Answers (1)

Pedro Louren&#231;o
Pedro Louren&#231;o

Reputation: 610

There are a couple of problems with your current approach.

The first one is that you shouldn't be using your reducer to get even more state, that's not its responsibility. A reducer's responsibility is simply, to reduce or, in other words, to derive a new state. It's literally a state machine that receives an action, a set of properties and decides how the next state should be. If you have an async action in there, you are mixing it with the action.

Action ---> Reducer ---> Store

The second problem seems to be that, even though you are trying to make the whole reducer asynchronous, you are not returning the result of newItem().

A simple solution

My suggestion as a solution would be:

  1. Move the newItem() method out of the reducer and simply return the newItem object
  2. Call the newItem() method in your UI, await for it, and call the action that dispatches ADD_ITEM with the result:
const item = await newItem();
dispatch({type: ADD_ITEM, item})
  1. Receive the required action data and use it to reduce the new state.
your_reducer: (state = [], action) => {
    case ADD_ITEM:
        return [...state, action.item]
}

I would recommend checking some redux examples.

Upvotes: 2

Related Questions