1

I wrote a react redux app, everyting working fine, now i am trying implement my initial data should be comes from API endpoint,

this is my postReducers.py file:

var initialState = {
  employees: []
};

var postReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_POST':
      return {
        ...state,
        employees: [...state.employees, action.data],
      };
    case 'EDIT_POST':
      return {
        ...state,
        employees: state.employees.map(emp => emp.id === action.data.id ? action.data : emp)
      };
      case 'DELETE_POST':
        console.log(action.data.id)
        return {
           ...state,
           employees: [...state.employees.filter((post)=>post.id !== action.data.id)],
        };
    default:
      return state;
  }
};


export default postReducer;

and this is my table.js file

import React, {Fragment} from "react";
import { connect } from "react-redux";
const axios = require('axios');

class Table extends React.Component {
    onEdit = (item) => {  //Use arrow function to bind `this`
        this.props.selectedData(item);
    }

    onDelete = (id) => {
        const data = {
            id,
        }
        this.props.dispatch({ type: 'DELETE_POST', data });
    }

    render() {
        return (
            <Fragment>
                <thead>
                    <tr>
                        <th scope="col">Name</th>
                        <th scope="col">Age</th>
                        <th scope="col">Edit</th>
                        <th>Delete</th>
                    </tr>
                </thead>
                <tbody>
                {this.props.employees.map((item, index) => (
                    <tr key={index}>
                        <td>{item.name}</td>
                        <td>{item.age}</td>
                        <td>
                            <button
                                type="button"
                                onClick={() => this.onEdit(item)}>EDIT
                            </button>
                            <button
                                onClick={ () => this.onDelete(item.id) }>DELETE
                            </button>
                        </td>
                    </tr>
                ))}
                </tbody>
            </Fragment>
        );
    }
}

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

export default connect(mapStateToProps)(Table);

and this is my App.js file

import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import Home from '../components/home'
import Contacts from '../components/contact'
import About from '../components/about'

class App extends Component {
  render() {
    return (
    <Router>
      <p>A simple webpack for django and react</p>
        <div>
          <nav className="navbar navbar-expand-lg navbar-light bg-light">
          <ul className="navbar-nav mr-auto">
            <li><Link to={'/'} className="nav-link"> Home </Link></li>
            <li><Link to={'/contact'} className="nav-link">Contact</Link></li>
            <li><Link to={'/about'} className="nav-link">About</Link></li>
          </ul>
          </nav>
          <hr />
          <Switch>
              <Route exact path='/' component={Home} />
              <Route path='/contact' component={Contacts} />
              <Route path='/about' component={About} />
          </Switch>
        </div>
      </Router>
    );
  }
}

export default App;

and this is my home.js file

import React from "react"
import Table from "../components/table"
import Form from '../components/form'

class Home extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
           selectedData: {name: '', age: ''},
           isEdit: false
        };
    }

    selectedData = (item) => {
       this.setState({selectedData: item,isEdit:true})
    }
    render() {
        return (
            <React.Fragment>   
              <Form selectedData={this.state.selectedData} isEdit={this.state.isEdit}/>          
            <table>
                <Table selectedData={this.selectedData} />
            </table>
            </React.Fragment>
        );
    }
}
export default Home;

this is my Form.js file:

import React, { Fragment } from "react"
import { connect } from 'react-redux'
const axios = require('axios');

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
      id: this.props.selectedData.id, 
      name: this.props.selectedData.name, 
      age: this.props.selectedData.age,
    };
    this.onHandleChange = this.onHandleChange.bind(this);
    this.submit = this.submit.bind(this);
  }


  submit(event) {
    const data = {
      name: this.state.name, 
      age: this.state.age, 
      email: this.state.email
    };
    if (this.props.isEdit) {
      data.id = this.props.selectedData.id;
      console.log('edit', data);
      this.props.dispatch({ type: 'EDIT_POST', data })
    } else {
      // generate id here for new emplyoee
      this.props.dispatch({ type: 'ADD_POST', data })
    }
  }

  onHandleChange(event) {
    this.setState({
      [event.target.name]: event.target.value
    });
  }

  componentDidUpdate(prevProps) {
    if (prevProps.selectedData.age !== this.props.selectedData.age) {  //Check on email, because email is unique
      this.setState({ name: this.props.selectedData.name, age: this.props.selectedData.age })
    }
  }



  render() {
    return (
      <form>
        <div className="form-group">
          <input onChange={(event) => this.onHandleChange(event)} value={this.state.name} name="name" type="text" />
        </div>

        <div className="form-group">
          <input onChange={(event) => this.onHandleChange(event)} value={this.state.age} name="age" type="number" />
        </div>

        <button onClick={(event) => this.submit(event)} type="button">
          {this.props.isEdit ? 'Update' : 'SAVE'}
        </button>

      </form>
    );
  }
}

export default connect(null)(Form);

and this is my index.js file:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from 'react-router-dom'

import App from "../client/components/App";

import { Provider } from 'react-redux'

import { createStore } from 'redux'
import postReducer from '../client/postReducer'

const store = createStore(postReducer)


// if we don't subcribe, yet our crud operation will work
function onStateChange() {
  const state = store.getState();
}

store.subscribe(onStateChange)

ReactDOM.render((
  <BrowserRouter>
      <Provider store={store}>
        <App />
      </Provider>
  </BrowserRouter>
), document.getElementById('app'))

Can anyone please help me to implement my initialState, so that when i visit the page or whe the table is loaded, the table should get data from API end point?

My API End point is: http://127.0.0.1:8000/employees/ it has only two field, name, and age

I am using axios for http request

I searched on stackoverflow and a man showed a possible duplicate post but that didnt solve my problem, coz, it was for react native

dudd
  • 372
  • 1
  • 4
  • 13
  • Possible duplicate of [Passing initial state from API call to createStore when react native application boots up](https://stackoverflow.com/questions/50315639/passing-initial-state-from-api-call-to-createstore-when-react-native-application) – Kiran Maniya Aug 25 '19 at 07:33
  • What about using componentDidMount() and calling action you need here? – Emil Aug 25 '19 at 07:43

1 Answers1

0

You can fetch the data in your home.js where you are using your Table component. You can fetch the data in componentDidMount() and pass data to your reducer using an action like SET_EMPLOYEES_LIST:

home.js:

import React from "react"
import Table from "../components/table"
import Form from '../components/form'
import { setEmployeesList } from './actions'
class Home extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
           selectedData: {name: '', age: ''},
           isEdit: false
        };
    }

    componentDidMount(){
       Axios.get(URL).then(res => this.props.setEmployeesList(res.data))
    }

    selectedData = (item) => {
       this.setState({selectedData: item,isEdit:true})
    }
    render() {
        return (
            <React.Fragment>   
              <Form selectedData={this.state.selectedData} isEdit={this.state.isEdit}/>          
            <table>
                <Table selectedData={this.selectedData} />
            </table>
            </React.Fragment>
        );
    }
}
const mapDispatchToProps = dispatch => {
   return {
      setEmployeesList: data => dispatch(setEmployeesList(data)) // Set the action you created in your component props
   }
}
export default Home;

action.js:

import {SET_EMPLOYEES_LIST} from './constants'
export const setEmployeesList = payload => ({ type: SET_EMPLOYEES_LIST, payload })

constants.js:

export const SET_EMPLOYEES_LIST = 'SET_EMPLOYEES_LIST'

postReducers.js:

import {SET_EMPLOYEES_LIST} from './constants'
const initialState = {
  employees: []
};

const postReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_EMPLOYEES_LIST:
      return {
        ...state,
        employees: action.payload,
      };
    case 'ADD_POST':
      return {
        ...state,
        employees: [...state.employees, action.data],
      };
    case 'EDIT_POST':
      return {
        ...state,
        employees: state.employees.map(emp => emp.id === action.data.id ? action.data : emp)
      };
      case 'DELETE_POST':
        console.log(action.data.id)
        return {
           ...state,
           employees: [...state.employees.filter((post)=>post.id !== action.data.id)],
        };
    default:
      return state;
  }
};


export default postReducer;
Majid Amiri
  • 580
  • 4
  • 14