简体   繁体   中英

React Native Redux: props not updating after API call

I am quite new to React / React Native / Redux so I feel I am doing something wrong.

The problem

I want to show a spinner while an API is called, and an error message once this API call fails. Props are not updating, and so the components don't show the desired message or spinner

The code (only the relevant chunks)

The component

class Home extends Component {

    componentWillMount() {
        this.props.tokenGet();
    }

    renderSpinner() {
        if (this.props.loading) {
            return (
                <Spinner size="large" />
            );
        }
        return null;
    }

    renderMessage() {
        if (this.props.message) {
            return (
                <Text style={{flex: 1, background: red, color: black}}>
                    { this.props.message }
                </Text>
            )
         }
         return null;
    }

    render() {
        return (
             { this.renderSpinner() }
             { this.renderMessage() }
        )
    }
}


const mapStateToProps = (state) => {
    const { auth } = state;
    const {
        loading,
        token,
        message
    } = auth || {
        loading: false,
        token: null,
        message: null
    };
    return {
        loading,
        token,
        message
    }
};


export default connect(mapStateToProps, { tokenGet } )(Home);

The action creator

export const tokenGet = () => {
    return (dispatch) => {
        dispatch({ type: 'TOKEN_GET_START'});

        // Perform the actual API call
        let requestToken = fetch(apiBaseUrl + "/tokens", {
             method: "POST",
             headers: {
                  'Accept': 'application/json',
                  'Content-Type': 'application/json'
             },
             body: JSON.stringify(.....)
        });
        Promise
             .race([timeout, requestToken])
             .then((response) => response.json())
             .then((responseJson) => {
                   ... not relevant ...
             })
             .catch((error) => {
                 dispatch({ type: 'TOKEN_GET_FAIL', payload: error});
             });

The timeout function, which gets called when the server fails to respond

let timeout = new Promise((resolve, reject) => {
    setTimeout(reject, 2000, 'Request timed out. Please check your internet connection.');
});

The reducer

import {
    TOKEN_GET_START,
    TOKEN_GET_SUCCESS,
    TOKEN_GET_FAIL
} from '../actions/types';

const INITIAL_STATE = {
    loading: false,
    token: null,
    message: null
};

export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case TOKEN_GET_START:
            return { ...state, loading: true };
        case TOKEN_GET_SUCCESS:
            return { ...state, loading: false, token: action.payload };
        case TOKEN_GET_FAIL:
            return { ...state, loading: false, message: action.payload };
        default:
            return state;
    }
};

The combined reducers

import { combineReducers } from 'redux';
import AuthReducer from './AuthReducer';

export default combineReducers({
    auth: AuthReducer
});

The actual behavior is that the props don't change and no message or spinner is visible. With some console logs I know that the API call ends because of the timeout. I am not sure if the state gets updated properly though. I don't know in at which point I can console log this.

It turned out to be because of the quotes in 'TOKEN_GET_FAIL'

That is a string and not the const I need. So I changed to TOKEN_GET_FAIL and it works.

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