0
votes

I converted this application https://codesandbox.io/s/3y77o7vnkp <--Please check this link into my react-native app and it works perfect. Since I implemented redux and redux-thunk I have a problem with fetching data.

There is a problem. I converted normal functions from this upper link to actions and reducers in react-native. For Example

handleSelect = itemValue => {
    this.setState(
      {
        ...this.state,
        base: itemValue,
        result: null,
      },
      this.calculate
    );
  };

TO actiontypes.js

export const HANDLE_FIRST_SELECT = 'HANDLE_FIRST_SELECT';

action.js

export const handleFirstSelect = itemValue => {
  return {
    type: actionTypes.HANDLE_FIRST_SELECT,
    itemValue: itemValue,
  };
};

and reducer.js

const initialState = {
  currencies: ['USD', 'AUD', 'SGD', 'PHP', 'EUR', 'PLN', 'GBP'],
  base: 'EUR',
  amount: '',
  convertTo: 'PLN',
  result: '',
  date: '',
  error: null,
  loading: false,
};
 const exchangeCurrencies = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.HANDLE_FIRST_SELECT:
      return {
        ...state,
        base: action.itemValue,
        result: null,
      };
...

Next step I used mapStateToProps and mapDispatchToProps in my component like this

const mapDispatchToProps = dispatch => {
  return {
    handleFirstSelect: itemValue =>
      dispatch(exchangeCurriencesActions.handleFirstSelect(itemValue)),
...

const mapStateToProps = (state) => {
  return {
    base: state.base,
    amount: state.amount,
    convertTo: state.convertTo,
    result: state.result,
    date: state.date,
  };
};

And I'm using now this.props

<PickerComponent
    selectedValue={this.props.base}
    onValueChange={this.props.handleFirstSelect}
/>

Until then, everything works ok. Now when I download data in this way with react-redux and redux-thunk (action.js) it stops working

export const fetchDataSuccess = data => {
  return {
    type: actionTypes.FETCH_DATA_SUCCESS,
    data: data,
  };
};

export const fetchDataFail = error => {
  return {
    type: actionTypes.FETCH_DATA_FAIL,
    error: error,
  };
};

export const fetchData = () => {
  return dispatch => {
    fetch(`https://api.exchangeratesapi.io/latest?base=${this.props.base}`)
      .then(res => res.json())
      .then(
        data => dispatch(fetchDataSuccess(data.rates)),
        e => dispatch(fetchDataFail(e)),
      );
  };
};

next reducer.js

...
case actionTypes.FETCH_DATA_BEGIN:
      return {
        ...state,
        loading: true,
        error: null,
      };
    case actionTypes.FETCH_DATA_SUCCESS:
      console.log('data', action.data);
      return {
        ...state,
        date: action.data.date,
        result: action.data.rates,
        loading: false,
      };
    case actionTypes.FETCH_DATA_FAIL:
      console.log('data', action.error);
      return {
        ...state,
        loading: false,
        error: action.error,
      };
...

In the next step added function fetchData into mapDispatchToProps and call this in componentDidMount like that

  componentDidMount() {
    if (this.props.amount === isNaN) {
      return;
    } else {
      try {
        this.props.fetchData();
      } catch (e) {
        console.log('error', e);
      }
    }
  }

and finnaly I add calculations for currencies in mapStateToProps. I change result like that result: (state.result[state.convertTo] * state.amount).toFixed(4),

and also I added applymiddleware into the store.

AND FINNALY THERE IS A ERROR

enter image description here

import React from 'react';
import HomeContentContainer from '../../containers/HomeContentContainer/HomeContentContainer';

class HomeScreen extends React.Component {
  render() {
    return <HomeContentContainer />;
  }
}

export default HomeScreen;

Anyone know how to resolve this problem? Where and what should I change the code?

1
I can't say definitively since the error line (at HomeScreen.js line 6) is not actually in the code you posted, but it definitely has something to do with result: (state.result[state.convertTo] * state.amount).toFixed(4),. You are trying to access a property on state.result which is initialized as a string ...result: '', in map state to props.Henry Mueller
I added HomeScreen.js into my postDaniel Gola
I would say most likely data.rates which you get back from the API is not being set....Michael Ceber
Mind you I checked the API call and it does return an object with rates...Michael Ceber
OHH, you know whats happening. The map state to props is being called as you would expect when you make the request before the data has come back, so the error occurs before result is even set! Add some code to check result being set and if null or has no properties map somthing else, otherwise do your function.Michael Ceber

1 Answers

0
votes

Following up on the comments to the question, please do review those...

In mapStateToProps protect your access to state.result, like this perhaps:

result: state.result ? (state.result[state.convertTo] * state.amount).toFixed(4) : null

, where null could also be 0 or whatever, your call. Your mapStateToProps is indeed getting called (at least) once before the API request is completed, so it needs to handle your initial state of state.result.

I find it confusing that the components property result and the state.result are different things, but this is just my opinion about naming.