0
votes

i have some problem i can't figure out. i have some component inside i'm using react-table plugin.

on componentDidMount method i have to call redux action which get data from api and then i'm passing this data to react-table.

here is my componentDidMount method where i call to redux action.

componentDidMount() {
    this.props.getData() 
}

here is my action:

export const FETCH_DATA_START = 'FETCH_DATA_START'
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS'
export const FETCH_DATA_FAILED = 'FETCH_DATA_FAILED'

export const getOffBoardingData = () => {
    return (dispatch) => {
        dispatch({
            type: FETCH_DATA_START
        })
        fetch(baseUrl, {
                credentials: "include",
                method: "GET",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                }
            })
            .then(res => res.json())
            .then((res) => {
                dispatch({
                    type: FETCH_DATA_SUCCESS,
                    payload: res.result
                })
            })
            .catch((err) => {
                dispatch({
                    type: FETCH_DATA_FAILED,
                    payload: 'error'
                })
            })
    }
}

and here is my reducer.

import { FETCH_DATA_START, FETCH_DATA_SUCCESS, FETCH_DATA_FAILED } from 'store/actions/getData'

let initialState = [{
    items: null
}]

export default (state = initialState, action) => {
    switch (action.type) {
        case FETCH_DATA_START:
            return {...state}
        case FETCH_DATA_SUCCESS:
            return { ...state, items: action.payload} 
        case FETCH_DATA_FAILED: 
             return {...state}
        default:
            return state
    }
}

everything work well here i think.

here is in my component i'm trying to make conditional rendering like:

 if (this.props.getDataReducer.items != null) {
        return (<div>
            <p>Loading...</p>
        </div>);
      } else { 
     return(
          <ReactTable className="-striped -highlight"
              data={this.props.getDataReducer.items}
              columns={columns} 
                                 />
       )
}

here is i make conditional rendering for my data. If items is null return some loading text else return react-table with data which came from api.

but i don't know how react-table trying to rendering when data null too.

where i return react-table i'm trying to make console.log my data but it's return undefined

sometimes component rendering without problem sometimes just giving error that data is undefined.

I make mistake about conditional rendering?

i tried to make that: component will wait to data and only when data will come that time component will be rendering.

where i make mistake?

3
try if (this.props.getDataReducer.items) { //react table } else { // loading }lochawala

3 Answers

0
votes

I think the problem you're having is setting your condition to specifically check for a null value. You should check if items is simply a truthy value. Since React-Table's data property accepts an array, you should also check that items has a length as well.

1) Update the condition in your component

 if (this.props.getDataReducer.items && this.props.getDataReducer.items.length >= 0) {
        return (<div>
            <p>Loading...</p>
        </div>);
      } else { 
     return(
          <ReactTable className="-striped -highlight"
              data={this.props.getDataReducer.items}
              columns={columns} 
                                 />
       )
}

2) Not sure if this is a typo, but the initial-state in your reducer looks messed up.

let initialState = [{
    items: null
}]

Your reducer is returning a new state object. if you were to spread the initial-state into it, you would get some unintended additional properties that wouldn't be useful to you. I believe you're looking for:

let initialState = {
    items: null
}
1
votes
  1. Your initial state is an array but I guess you wanted an object.
let initialState = [{
    items: null
}]

what you want is

let initialState = {
    items: null
}

To put it in words, in the first case getDataReducer returns an array with {items: null} in the first position,
so to get items you need to getDataReducer[0].items.
But if you change it to an object you can simply, getDataReducer.items.

  1. And more importantly, your check logic is inverted.
 if (this.props.getDataReducer.items != null) {
   // ...loading component
 }

should be

 if (this.props.getDataReducer.items === null) {
    // ...loading component
 }
  1. Consider refactoring, and adding a isLoading variable in your state,
    which you should set to true in the FETCH_DATA_START and to false in the SUCCESS and FAILURE cases.
    Checking if the items are null won't necessarily mean that they are loading, as your app and code grows it is better to be more specific about what you mean.
0
votes

You can make the condition simpler to handle for undefined and null:

 if (this.props.getDataReducer.items) {
        return (<div>
            <p>Loading...</p>
        </div>);
      } else { ... 
 }

One more good practise for code clarity, it's best to have custom functions handle these conditions, so that render() has only one return.