简体   繁体   中英

How to access async function from Redux Action passed into Redux Thunk?

I am trying to refactor code from Javascript React to Typescript React.

I have an action here which performs an API call and returns a function with dispatch

My UserActions.ts file looks like this

export const login = ({username, password}) => async (dispatch: any) => {
  try {

    let r = await apiCall(); //performing api call here

    return r.code; //returning the custom responseCode here from my server

    console.log(auth)
  } catch (err) {
    throw new Error(err);
  }
}

In my component file MyComponent.ts there is a member function for the component class

public formSubmit = (e: React.FormEvent) => {
        e.preventDefault();

        const { password, email } = this.state;

        this.props.login({
            email,
            password,
        }).then(responseCode => {
                //I want to access responseCode here
        });
}

The connection to Redux looks like this in MyComponent.ts

const mapStateToProps = (store: IAppState) => {
    return {

    }
}

export default connect(mapStateToProps, {
    login
})(SignIn);

So, as you can see, the login actually returns a function which is passed into Redux Thunk Middleware and is then passed in this.props to MyComponent

To access return variable from function, I have to type the outer function in login action UserActions.ts .

So how do I access with proper types ? Because typescript won't allow me to put this.props.login().then() in MyComponent.ts

The best practise is to dispatch action and populate the data to reducer. Try to avoid passing data back from async functions. You can have a AuthReducer and update the data and use it directly in the component.

export const login = ({username, password}) => async (dispatch: any) => {
    let r = await apiCall(); //performing api call here
    dispatch({ type: 'UPDATE_AUTH', payload: auth })
}

and in your reducer

case 'UPDATE_AUTH':
 return { ...state, ...action.payload }

and in your component

const mapStateToProps = ({ auth }) => ({ auth })

export default connect(mapStateToProps, {
    login
})(SignIn);

I didn't know the actual Typescript way to do it, so I used the any workaround

Instead of doing

this.props.login({
            email,
            password,
        }).then(responseCode => {
                //I want to access responseCode here
        });

You can just do

const responseCode:any = await this.props.login({email, password});

Typescript is checking await here and I'm casting the returned object to any and in runtime the actual responseCode is returned from Redux Thunk

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