I'm from angular background and trying to learn reactjs by implementing a website(https://tmdbredux.herokuapp.com). Now and then I face issues and try to find answers, but this one I havn't found a proper way to do it.
How to render react components after only successful asynchronous calls
class CardComponent extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
//doing some asynchronous call here which dispatches an action
//and updates the state -> which inturn renders the component again.
//I want component to be rendered after this happended. Is it possible ?
}
//This render is begin called even before props getting updated
render() {
return (
<div>Component Rendered Here </div>
)
}
}
Being from angular background I'm facing tough time to handle null conditions on object, because without props getting updated with appropriate data object might throw errors.
Please suggest any good practices or solution for the problem
Thanks in Advance
Jason Nutter
Senior Front End Engineer @ Porch.com
componentDidMount(){
//got data from AJAX call
this.setState({data:data});
}
render(){
this.state.data ? <div>{ this.state.data.map((item,index) =>
<span key={index}> {item.value} </span>
)} </div>
: <div> Loading ... </div>
}
You've to write a ternary operator (an IF-else will also do, but I prefer ternary). There will be 2 states , the initial state when there's no data and the state where you've the data from the AJAX call. Whenever you set the state using setState function react will automatically call the render method and change your view according to the data. Hope this helped.
I think this chapter within the react docs is quite self-explanatory: facebook.github.io/react/docs/conditional-renderi…
I can think of two ways to achieve this without complicating things:
You can let the parent component handle the async calls and maintain a state. Once the data is available and state is updated, you can render the CardComponent as a child (and pass the state data as props).
If you are using some sort of state management solution or just keeping a global state, you can define the needs for each component. Before doing route transitions, you just need to go through the needs of the component, make necessary AJAX calls and keep the data ready in the global state. Once the required data is present in the global state, you can trigger route transition and mount the component.
You don't have to check for null values (and return early) if you use the above solutions.
I have to say I cheat with a component
const BlueCircleAjaxLoader = ({loaded, children}) => {
const renderChildren = () => {
if (loaded) {
return (
<div className="child-wrapper">
{children}
</div>
)
}
return (
<div className='uil-ring-css' style={{transform : "scale(0.64)"}}>
<div />
</div>
)
};
return (
<div className="ajax-loading-container">
{renderChildren()}
</div>
);
};
export default BlueCircleAjaxLoader;
In order to make the exemple as simple as possible, I'm using the component internal state to control if the asynchronous call has already returned or not. Like that:
class CardComponent extends Component {
componentDidMount() {
const self = this;
server.getSomeData(data => self.setState({ data: data }));
}
//This render is begin called even before props getting updated
render() {
return (
<div>
<h1>{'This will always render'}</h1>
{ this.state && this.state.data &&
<div>{'This will just render after the return of the async call'}</div>
}
</div>
)
}
}
The trick here is to use the component internal setState. Every time you call setState, React will force the component to render again.
So, suppose you have an asynchronous function getSomeData that will call a callback function when data is fetched from server. When this function is called, I set the state of the component with the data and the render function is called again.
Inside render, I use an AND operation to check if the data property is available in state. Since state is not initialized by default, I have to test if state and state.data are available. Because in JavaScript, the result of an AND operation is always the last expression (from left to right), it will return the <div> to be rendered.
This is a very simple technic, but it works pretty well... When you get deeper into React, you'll find a lot of best practice guides recommending to avoid the use of internal component state (for example, stripping out the async call from inside the component and passing the data as a component property), which offers some advantages in terms of maintainability. But that is another history...
You should define the states for your component e.g. "loading, error etc." So when you api call is failed or still loading you may use those props to do some conditional rendering .
So, if you are using Redux, just define some flags in your reducers for error and loading states, then check those in your JSX conditionally. You may also define an initial state for your reducer if you don't want null conditions for your objects (You can also use defaultProps but keeping all of them in redux is better IMO.)
Note: You can return "null" from a JSX block if you don't want to render that part.
David Miranda
it is easy... u should use a default state like mine
state = { automation: { campaigns: [], goals: { roi: {} }, status_configuration: {}, bid_configuration: { cpc: {} } } }