sbkl
sbkl

Reputation: 2321

Async call with react native and redux , thunk

I have been following this tutorial to integrate redux into my react native app.

https://github.com/jlebensold/peckish

On my Home view, I'm not able to call the functions from my action folder.

One difference is that I'm using react-navigation in my app. Wonder if I need to integrate redux with react navigation to be able to use redux for all data?

Below is the full implementation code I have been doing.

On the Home screen, I call the fetchSite function on ComponentDidMount to launch an async call with axios. But I can't even access to this function.

Sorry for this long post but I can't figure out how to make this work so quite difficult to make a shorter code sample to explain the structure of my app.

Let me know if any question.

index.ios.js

import React from 'react'
import { AppRegistry } from 'react-native'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose} from 'redux'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'

import reducer from './app/reducers'
import AppContainer from './app/index'


// middleware that logs actions
const loggerMiddleware = createLogger({ predicate: (getState, action) => __DEV__  });

function configureStore(initialState) {
    const enhancer = compose(
        applyMiddleware(
            thunkMiddleware, // lets us dispatch() functions
            loggerMiddleware,
        ),
    );
    return createStore(reducer, initialState, enhancer);
}

const store = configureStore({});

const App = () => (
    <Provider store={store}>
        <AppContainer />
    </Provider>
);

AppRegistry.registerComponent('Appero', () => App;

reducers/index.js

import { combineReducers } from 'redux';
import * as sitesReducer from './sites'

export default combineReducers(Object.assign(
    sitesReducer,
));

reducers/sites.js

import createReducer from '../lib/createReducer'
import * as types from '../actions/types'

export const searchedSites = createReducer({}, {
    [types.SET_SEARCHED_SITES](state, action) {
        let newState = {};
        action.sites.forEach( (site) => {
            let id = site.id;
            newState[id] = Object.assign({}, site, { id });
        });
        return newState;
    },

});

../lib/createReducer

export default function createReducer(initialState, handlers) {

    return function reducer(state = initialState, action) {
        if (handlers.hasOwnProperty(action.type)) {

            return handlers[action.type](state, action)
        } else {
            return state
        }
    }
}

../actions/types

export const SET_SEARCHED_SITES = 'SET_SEARCHED_SITES';

AppContainer in ./app/index

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { ActionCreators } from './actions';

console.log(ActionCreators); //Properly gathered the functions from the actions folder

import { Root } from './config/router';

window.store = require('react-native-simple-store');
window.axios = require('axios');

class App extends Component {
    render() {
        return (
            <Root />
        )
    }
}

function mapDispatchToProps(dispatch) {

    return bindActionCreators(ActionCreators, dispatch);
}

export default connect(mapDispatchToProps)(App);

ActionCreators in './actions';

import * as SiteActions from './sites'

export const ActionCreators = Object.assign({},
    SiteActions,
);

Actions in './actions/sites'

import * as types from './types' //See above

export function fetchSites(token) {

    return (dispatch, getState) => {

        let instance = axios.create({
            baseURL: url + 'api/',
            timeout: 10000,
            headers: {'Accept' : 'application/json', 'Authorization' : 'Bearer ' + token}
        });

        instance.get('/sites?page=1')
            .then(response => {

                console.log(response.data.data);

                dispatch(setSearchedSites({sites: response.data.data}));

            }).catch(error => {

                console.log(error);
        });

    }
}

export function setSearchedSites({ sites }) {

    return {
        type: types.SET_SEARCHED_SITES,
        sites,
    }
}

Root file for navigation based on react-navigation I made it as simple as possible for this example.

import React from 'react';

import {StackNavigator} from 'react-navigation';

import Home from '../screens/Home';

export const Root = StackNavigator({
    Home: {
        screen: Home,
    }
});

And finally my Home screen

import React, {Component} from 'react';
import { connect } from 'react-redux';
import {Text, View} from 'react-native';

class Home extends Component {

    componentDidMount()
    {
        let token = "12345678" //Just for this example
        this.props.fetchSites(token).then( (response) => {
            console.log(response);
        });
    }

    render() {

        return (
            <View>
                <Text>This is the Home view</text>
            </View>
        );
    }
}

function mapStateToProps(state) {
    return {
        searchedSites: state.searchedSites
    };
}

export default connect(mapStateToProps)(Home);

Upvotes: 0

Views: 2472

Answers (1)

Kishan Vaghela
Kishan Vaghela

Reputation: 7938

To use action methods you need to connect in home screen like this

import { fetchSites } from '<your-path>'

// your Home's other code.

const mapDispatchToProps = (dispatch) => {
    return{
        fetchSites:dispatch(fetchSites())
    } 
}

export default connect(mapStateToProps,mapDispatchToProps)(Home);

after that you can use fetchSites as this.props.fetchSites whenever you want.

Upvotes: 1

Related Questions