1

Can someone please help me with this. I can see the response from api but when the page renders, response is too late to render. I could not find what I'm doing wrong. I would really appreciate if someone could explain. Thanks

Below is my reducer

    export default function reducer(state = {
  responseCode : {
  },
  fetching: false,
  fetched: false,
  error: null
}, action){
  switch(action.type){
    case 'FETCH_RESPONSECODE_PENDING' : {
      return { ...state, fetching: false}
      break;
    }
    case 'FETCH_RESPONSECODE_ERROR' : {
      return { ...state, fetching: false, error: action.payload }
    }
    case 'FETCH_RESPONSECODE_FULFILLED' : {
      return{ 
        ...state,
        fetching: false,
        fetched: true,
        responseCode: action.payload
      }
      break;
    }
  }
  return state;
}

//SearchResponseCode Component

    handleSearch(event){
    event.preventDefault();
  }

render(){
    return (
      <form>
        <div className="col-xs-8">
          <input type="number" className="form-control" placeholder="e.g. main mailing response code or recruitment campaign code" ref="responseCode" />
        </div>
        <div className="col-xs-4">
          <button className="btn btn-default" onClick={this.handleSearch.bind(this)}>Search</button>
        </div>
      </form>

    )    
  }

//Main Component

import SearchResponseCode from './search-response-code'
import { connect } from 'react-redux'
import { fetchResponseCode } from '../../actions/responseCodeActions'

@connect((store)=>{
  return{
    responseCode: store.responseCode.responseCode
  };
})
  fetchResponseCode(){
    this.props.dispatch(fetchResponseCode(brandUrl, 2570010))
  }


  render(){
    const { responseCode } = this.props
    console.log(this.responseCode)
    return(
      <Tabs selectedIndex={0}>
        <TabList>
          <Tab>Search By Responce Code</Tab>
          <Tab>Search By Item Code</Tab>
          <Tab>Searh All</Tab>
        </TabList>
        <TabPanel>
          <SearchResponseCode fetchResponseCode={this.fetchResponseCode.bind(this)} />
        </TabPanel>
        <TabPanel>
          <SearchItemCode />
        </TabPanel>
        <TabPanel>
        </TabPanel>
      </Tabs>  
    )
  }
}

//Action

import axios from 'axios'

export function fetchResponseCode(brandUrl, responseCode){
  let url = brandUrl + '/api/offer/' + responseCode;

  return function(dispatch){
    axios.get(url)
      .then((response) => {
        dispatch({
          type : 'FETCH_RESPONSECODE_FULFILLED',
          payload : response.data
        })
      })
      .catch((err) => {
        dispatch({
          type : 'FETCH_RESPONSECODE_ERROR',
          payload : err
        })
      })
  }
}
4
  • 1
    Your SearchResponseCode Component isn't all there, which might matter to help you. Axios uses promises to dispatch to the store, which should trigger a render when the response come back. In other words, the response isn't coming in too late for the render, you are probably not using the correct part of the state. Commented Feb 23, 2017 at 0:35
  • Hi @JoPeyper Thank you for reply. Can you find out what I am doing wrong? Commented Feb 23, 2017 at 4:34
  • @Mesmerize86 What exactly is happening when you click the Search btn in your SearchResponseCode component? The page waits for a bit before it re-renders? Commented Feb 23, 2017 at 7:27
  • At the moment SearchResponseCode component is not doing anything. But what I would like to get from that component is when you click on search button it should pass the input value as a parameter to call an api. I don't think the page waits for re-render. I do get response but before the data loads the page render quickly and it didn't get chance to load the response. Commented Feb 23, 2017 at 22:59

3 Answers 3

4
  • why you want to hold the render until data comes .Thats wrong practice and makes your webapp slower.
  • and beauty of react is as data comes it updates the part of the View and you can see the data.
  • you can send data as prop to other component and place a check where you want to load your async data to avoid errors ,something like this -

//suppose you will get an address object from api ,which will contain city ,area ,street ,pin code etc
// address={} intially address is a blank object
render(){
    return(
        (typeof address.area!='undefined')?
        <div>
        <div>{address.city}</div>
        <div>{address.street}</div>
        <div>{address.pin_code}</div>
        <div>{address.area}</div>
        </div>
        :<div>loading....</div>
    )
}

  • follow this approach ,in this way user can see something in fraction of seconds,instead of waiting for fulldata to come
  • above is just one way ,if you could explain yourcode more ,i might able to help
Sign up to request clarification or add additional context in comments.

Comments

1

Nothing will happen since you're not invoking anything inside your SearchResponseCode.handleSearch.

You'll need to call the fetchResponseCode inside that function.

//SearchResponseCode component

handleSearch(e) {
  e.preventDefault();
  const input = this.refs.responseCode.value; //you should avoid using ref="string"
  this.props.fetchResponseCode(input);
}

Of course you'll need to modify your fetchResponseCode method inside your main component to accept the parameter and pass it to the action to dispatch.

Hope this helps.

4 Comments

That's right. I have a this.props.fetchResponseCode(input); in my handleSearch now. But when it comes to fetchResponseCode(input) function, I have dispatch my action. fetchResponseCode(input){ this.props.dispatch(fetchResponseCode(brandURL, input)) } when I log console I get my response. However in render when i console.log(this.props.response.numOfAddOnItems), i am getting an error Cannot read property 'numOfAddOnItems' of undefined.
I don't see any reference of numOfAddOnItems in your code. Not sure how to help you.
numOfAddOnItems is just an item of an object from my response. I tried to upload image and realise stackoverflow doesn't support it. However I have quickly listed to make it more clear. .response .numOfAddOnItems : 1 .addOnItems: Array[0] .dataRange: Object I hope I make it clear.
just would like to add, I set 2 secs timer to test it. And I'm getting the value. I need to load that response before it render
0

I know the question got answer but I came with a very nice solution which I want to share.I hope it might help many coders which are seeing my answer as the problem was frustrating to me as well but I concluded with a great way!

Do you know "optional chaining" if not see this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining


for any data which is undefined on first render while using redux.

I will take the example of my friend @rajatGupta

//suppose you will get an address object from api ,which will contain city ,area ,street ,pin code etc
// address={} intially address is a blank object
render(){
    return(
        address?.area?
        <div>
        <div>{address.city}</div>
        <div>{address.street}</div>
        <div>{address.pin_code}</div>
        <div>{address.area}</div>
        </div>
        :<div>loading....</div>
    )
}

Notice this portion only : address?.area I used optional chaining if the data is undefined the app will not crash and if there comes some value in the "address.area", you can use it in the desired way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.