1

I’m building a Django-React application (Django API on its standalone server on port 8000 and React front-end on its standalone server on port 3000) using axios to fetch data from the Django server and Redux to dispatch the data. So, I created the redux action like this:

// GET TRANSACTIONS: /action/transactions.js

import axios from 'axios';
import { GET_TRANSACTIONS } from './types';
export const getTransactions = () => (dispatch) => {
  axios.get('http://127.0.0.1:8000/api/transaction')
   .then((res) => {
     dispatch({
       type: GET_TRANSACTIONS,
       payload: res.data,
     });
   }).catch((err) => console.log(err));
};

And in the the React view to get the data from redux store I have this:

// React Views :

import React, {Component,} from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getTransactions } from '../../../../actions/transactions';
import './transfert.css';

const initialState = {
  transactions: [],
};

const propTypes = {
  transactions: PropTypes.array.isRequired,
};

class Transfert extends Component {
  componentDidMount() {
    getTransactions();
  }

  render() {
    return (
      <div className="table">
  
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  transactions: state.transactions.transactions,
});

export default connect(mapStateToProps, { getTransactions })(Transfert);

The problem is that I’m not getting the data from the Django server in the reduxdevtools. It displays nothing, only says: type(pin):"@@INIT". Whereas I should be getting all the transactions from there.

Checking the Django server, I found that the Django console says:

code 400, message Bad request version ('\x9bú|$Lª\x01Þù\x83!ów·È\x803<Æ\x00"ZZ\x13\x01\x13\x02\x13\x03À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00') [27/Jan/2022 15:56:59] You're accessing the development server over HTTPS, but it only supports HTTP.

And I thought of setting the SECURE_SSL_REDIRECT to false in the Django setting. So, I set it there like this:

SECURE_SSL_REDIRECT=False SESSION_COOKIE_SECURE=False CSRF_COOKIE_SECURE=False

But to not avail, I’m still not hitting the right point. All my console logging rendered no result, and I’m even more confused, not knowing whether the problem is in the axios call: axios.get('http://127.0.0.1:8000/api/transaction') Or from the getTransaction() whitin the React Transaction.js (Rect View). Or is there anything with the

const mapStateToProps = (state) => ({
  transactions: state.transactions.transactions,
});

Or with the export default connect(mapStateToProps, { getTransactions })(Transfert);

NOTE: In the transaction.jsx view I earlier called:

componentDidMount() {
  this.props.getTransactions();
}

With the this.props but the error says: “Must use destructuring props assignment” That is why I changed it to current one:

componentDidMount() {
    getTransactions();
}

Any help is very much appreciated. Here I’m seriously stuck.

Himmels DJ
  • 395
  • 5
  • 20

2 Answers2

3

After struggling with this issue throughout this couple of weeks, I found the answer. First of all the “Cors header” mentioned by @Derek S, which I ignored in the beginning was mandatory. But after installing and configuring it, the issue was persisting because of some other misunderstandings which I got to have a good grasp of now.

  1. I was taking example on a tutorial in which several redux folders were created for each of the redux steps: Reducer folder – actions folder– and a store.js file separated. So the main redux action inside my react component was the getTransaction() function declared as:

    import axios from 'axios';
    import { GET_TRANSACTIONS } from './types';
    export const getTransactions = () => (dispatch) => {
      axios.get('http://127.0.0.1:8000/api/transaction')
        .then((res) => {
          dispatch({
            type: GET_TRANSACTIONS,
            payload: res.data,
          });
        }).catch((err) => console.log(err));
       };
     };
    

    The insanity in this is that I was using redux inside a class based component and the getTransactions() function was not triggered, hence nothing was dispatched to the redux store. That was the issue number one. So instead of creation the getTransaction() inside a separated redux actions folder, I threw it’s content straight inside the mapDispatchToProps of the target class componentlike this:

    const mapDispatchToProps = () => (dispatch) => {
      axios.get('http://127.0.0.1:8000/api/transaction')
        .then((res) => {
          dispatch({
            type: GET_TRANSACTIONS,
            payload: res.data,
          });
          console.log(res.data);
        }).catch((err) => console.log(err));
    };
    

    And afterward instead of

    export default connect(mapStateToProps, { getTransactions })(Transfert); I rather did export default connect(mapStateToProps, mapDispatchToProps)(Transfert); And the redux devtools beautifully displayed the transactions grabbed from API: result is here

  2. Another misunderstanding was to be following other people’s suggestions to configure the cors header for Django, and they were suggesting to add const cors = require("cors"); and to have: export const getTransactions = () => (dispatch) => {
    axios({ method: 'get', url: ‘http://127.0.0.1:8000/api/transaction’ withCredentials: false, content-type: text/plain params: { access_token: SECRET_TOKEN, },
    }); };

But this was just another huge pain in the ass, since cors header should only be configured in the backend (the server side) in my case the django API, and not inside the axios' call. So, I got rid of all those suggestions from the react frontend app and kept the component as simple as possible:

import React, {Component,} from 'react';
import { connect } from 'react-redux';
import axios from 'axios';
import { GET_TRANSACTIONS } from '../../../../actions/types';
import PropTypes from 'prop-types';
import './transfert.css';

const initialState = {
  transactions: [],
};

const propTypes = {
  transactions: PropTypes.array.isRequired,
};

class Transfert extends Component {
  render() {
    return (
      <div className="table">
  
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  transactions: state.transactions.transactions,
});
const mapDispatchToProps = () => (dispatch) => {
  axios.get('http://127.0.0.1:8000/api/transaction')
    .then((res) => {
      dispatch({
        type: GET_TRANSACTIONS,
        payload: res.data,
      });
      console.log(res.data);
    }).catch((err) => console.log(err));
};
const connectToStore = connect(mapStateToProps, mapDispatchToProps);
const ConnectedComponent = connectToStore(Transfert);
export default connect(mapStateToProps, mapDispatchToProps)(Transfert);

And now it works fine as the API is able to forward the data: as shown here

Himmels DJ
  • 395
  • 5
  • 20
1

To me this looks like a problem with your Django server. The error indicates that you are trying to use https to access the api which only supports http, but according to your code you are using http.

Open the debugger in your browser, what does the network traffic look like when the call is made? Is any error returned? Does a prefetch (OPTION) request occur and return OK?

If it is rejected before the actual request is called then there's a configuration issue somewhere. Likely CORS or https instead http.

Derek S.
  • 71
  • 1
  • 9
  • The network traffic gives nothing, as well as console, in chrome browser. Indeed for the mobile app that I built with react-native I used ngrock to convert http to https, but with react I think http could be routed. In fact I tested the api with postman and it worked fine, I received the "transactions" with same url: http://127.0.0.1:8000/api/transaction from postman – Himmels DJ Jan 27 '22 at 17:31
  • @HimmelsDJ If it worked fine in Postman but not in the browser, I suspect it is a CORS issue. The browser will reject requests if CORS is not configured correctly, postman will not. What do the headers look like when sent from the browser? – Derek S. Jan 27 '22 at 17:51
  • Ok thanks, I didn't know that. How can I configure that. I'm using django 3.2.11 – Himmels DJ Jan 27 '22 at 17:57
  • I set no header. I have this: export const getTransactions = () => (dispatch) => { axios.get('http://127.0.0.1:8000/api/transaction') .then((res) => { dispatch({ type: GET_TRANSACTIONS, payload: res.data, }); }).catch((err) => console.log(err)); }; – Himmels DJ Jan 27 '22 at 18:01
  • Open the network tab in your browser dev-tools, click on the network call you sent (should say `transaction` or something similar), then click on the headers tab to see what headers you sent and what the server sent back. – Derek S. Jan 27 '22 at 18:07
  • See here to enable CORS in Django (https://stackoverflow.com/questions/35760943/how-can-i-enable-cors-on-django-rest-framework) – Derek S. Jan 27 '22 at 18:10
  • I understand how CORS header is mandatory for ServerA to fetch data from server B, and I set I it up and configured properly. But the part you don't take into consideration is that I'm not fetching data straight from react view, but from Redux action, and then dispatch it to the views. And one way to test whether the data is fetched or nor is throught ReduxDevTools, but there the redux action gives type(pin):"@@INIT". – Himmels DJ Jan 28 '22 at 01:21
  • Your answer helped as a road map – Himmels DJ Feb 02 '22 at 18:04