0

here is my reducer:

export default function(state=[], action){
    switch (action.type) {
        case FETCH_PLACES: 
            return [action.payload.data]; 
    }
    return state;
}

and here is my flight container:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import moment from 'moment';

class FlightList extends Component {

    renderFlights(flightData){
        const result = flightData.data.length;     
        console.log(flightData);  
        var rows = [];
        for (var i = 0; i < result; i++) {
            rows.push(
            <tr key={i} >
                <td>{i+1}</td>,
                <td>{flightData.data[i].airlines[0]}</td>,
                <td>{flightData.data[i].route[0].flight_no}</td>,
                <td>{flightData.data[i].mapIdfrom}</td>,
                <td>{flightData.data[i].mapIdto}</td>,
                <td>
                    {
                        moment.unix(flightData.data[i].dTime).format("YYYY-MM-DD HH:mm")
                    }
                </td>,
                <td>
                    {
                        moment.unix(flightData.data[i].aTime).format("YYYY-MM-DD HH:mm")
                    }
                </td>,
                <td>{flightData.data[i].conversion.EUR} Euro</td>
            </tr>
            );
        }
        return <tbody>{rows}</tbody>;
    }   

    render(){
        return (
            <table className="table table-hover">
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Airline</th>
                        <th>Flight Number</th>
                        <th>From</th>
                        <th>To</th>
                        <th>Departure</th>
                        <th>Arrival</th>
                        <th>Cost</th>
                    </tr>
                </thead>
                    {this.props.flights.map(this.renderFlights)}
            </table>
        );
    }
}

const mapStateToProps=({ flights })=>{
    return { flights };
};

export default connect(mapStateToProps)(FlightList);

after I used redux-thunk when I try to run my application i get the following error:

Uncaught TypeError: Cannot read property 'data' of undefined

I tried to figure out what is causing this, if at my reducer i changed [action.payload.data] to [action.payload] then I get the error:

Uncaught TypeError: Cannot read property 'length' of undefined

here is my src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';

//import ReduxPromise from 'redux-promise';
import thunk from 'redux-thunk';


import App from './components/app';
import reducers from './reducers';

//const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
const store = createStore(reducers,applyMiddleware(thunk));

ReactDOM.render( 
  <Provider store={store}> 
  <App /> 
  </Provider> 
  , document.querySelector('.container'));

but no matter what I always get a JSON file that contains all the information I need and in my container I try to publish them in a table formt. I dont get what is causing this. is there any way to fix this without changing my source file to what it wa before?

UPDATE

import axios from 'axios';
import moment from 'moment';

const ROOT_URL = `https://api.skypicker.com/flights`;

//to keep out action type consistent between our action creator and our action reducers
export const FETCH_PLACES = 'FETCH_PLACES';

export function createQueryString(obj){
    const Qstring = require('querystring'); 
    const newQuery = Qstring.stringify(obj);
    return newQuery;
}

export function fetchPlaces(query) {

    let skypicker = {
        flyFrom: query.from,
        //to: query.to,
        dateFrom: query.startDate,
        dateTo: query.finishDate,
        price_to: query.budget,
        partner: "picky"
        //partner_market: "yout id"
    };

    const FormattedDateFrom = moment(skypicker.dateFrom).format('DD/MM/YYYY');
    const FormattedDateTo = moment(skypicker.dateTo).format('DD/MM/YYYY');
    skypicker.dateFrom = FormattedDateFrom;
    skypicker.dateTo = FormattedDateTo;

    const queryString = createQueryString(skypicker);
    const url = `${ROOT_URL}?${queryString}`;
    const request = axios.get(url);

    return {
        type: FETCH_PLACES, 
        payload: request
    };

}
S. N
  • 3,456
  • 12
  • 42
  • 65

1 Answers1

1

You did not include your action creator. The problem is in the way you work with redux-thunk.

  1. You dispatch action in your component/container
  2. If the dispatched action returns function then redux-thunk will execute that function
  3. Inside that function, you have to dispatch another action that will return an object (type and the data you got from API)

Edit:

This code snippet should do the work. If everything is good you should just replace your fetchPlaces action creator with my fetchPlaces action creator.

export function fetchPlaces(query) {
  // This is your thunk because we are not retuning object but a function redux-thunk will execute this function
  return function(dispatch) {
    const skypicker = {
      flyFrom: query.from,
      dateFrom: query.startDate,
      dateTo: query.finishDate,
      price_to: query.budget,
      partner: 'picky',
    }

    const FormattedDateFrom = moment(skypicker.dateFrom).format('DD/MM/YYYY')
    const FormattedDateTo = moment(skypicker.dateTo).format('DD/MM/YYYY')
    skypicker.dateFrom = FormattedDateFrom
    skypicker.dateTo = FormattedDateTo

    const queryString = createQueryString(skypicker)
    const url = `${ROOT_URL}?${queryString}`
    axios.get(url).then(function(response) {
      // If request was successful you want to dispatch new action
      dispatch({
        type: FETCH_PLACES,
        payload: response,
      })
    })
  }
}
Michal
  • 4,952
  • 8
  • 30
  • 63
  • can you help me do it? – S. N Feb 05 '18 at 15:53
  • Sure but you have to share action creators where you: 1) get data from api 2) send data to store – Michal Feb 05 '18 at 15:54
  • can we do it in chat? – S. N Feb 05 '18 at 15:55
  • 1
    I added my actions – S. N Feb 05 '18 at 15:59
  • Give me a minute I think I can see the bug :) – Michal Feb 05 '18 at 16:08
  • DONT WORRY i FIXED IT, I HAVE ANOTHER PROBLEM IF U WANT TO HELP! – S. N Feb 05 '18 at 16:10
  • I hope you did not call API from reducer :D – Michal Feb 05 '18 at 16:13
  • 1
    I used your first answer and I realized I am doing it wrong so I corrected it, and now I can see another version that works, thanks a lot. – S. N Feb 05 '18 at 16:18
  • i want to do the same for skyscanner but in my actions I have to combine 4 arrays into 1 array , its different from this one you just get one array of data, do you know how I can do that> – S. N Feb 05 '18 at 16:19
  • Call API 4 times. (async await would help so that you don't have to nest `axios.get(url).then(function(response) {` and then do the same thing. `dispatch(type, data)`. Redux and redux-thunk is quite confusing when you start using it but it will get easier in a day or two. – Michal Feb 05 '18 at 16:20
  • can I discuss something with on chat? – S. N Feb 05 '18 at 16:22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164569/discussion-between-michal-and-s-n). – Michal Feb 05 '18 at 16:22