A week into learning React, and I've hit a snag.
So, I have an action/reducer setting up an external API to pass the payload into the state for my component to render some of the values out in a subcomponent (being passed as a prop object) - however, it takes a few seconds for the API to respond and obviously I cant ask react to render any values before then, as they return null and crash react..
Best practise? Set default values for the state values until the state gets updated to avoid the null errors? Is there a better way?
Have tried a conditional render on the subcomponent (which will render the values) but didn't work.
Any advice greatly appreciated!
You must first set some initial value of state inside of reducers which is generally null or empty object. Now inside of your render method you must use conditional rendering and return appropriate jsx from that. This is the standard way to get data from APIs and then rendering it inside of the component. This could probably help you.
Related
I have tried to find and answer but couldn't. I hope someone can clear this up.
How does the DOM render without errors if the data that is passed to components as props isn't fetched yet?
Let's say you want to map the props to a child component. The props don't exist yet. The data to populate the whole downstream of components isn't there.
Shouldn't the first render then cause an error since all logic performs on empty props?
I think it's better to just return null from component, if some data is missing in props.
Suppose you want to pass an id of type string, then you can set an empty string In useState and later update it using setState after fetching the data. Thus there shouldn’t be any error.
Is possible to save the value of a prop in the data of the component for the next renderizing?
I mean, I want to update the data component from Vue and in the new instance get the value of a prop of the before instance
As you have stated, re-rendering means just that...rendering again. :)
So the short answer would be no, you can not save prop value within a component and use it after re-rendering.
You say that every minute you are fetching some data that later on you will be doing some logic on. As suggested use Vuex for that, save that data before re-rendering and the use it as you like.
One of many Vue.JS good point is a very well written documentation. You need Vuex so here it is: https://vuex.vuejs.org/
I use componentDidMount() method in my parent React component to fetch some data from API, which are then saved in redux-state.
In my render method, I have another component which should use data from the global redux-state.
I can send data to my child component via props or I can load them using mapStateToProps().
If I try to console.log or assign data to var from props in my child component constructor or in componentDidMount() method, I'm not getting my data as expected (I'm getting initial state).
Console.log in my render method will show me initial state at first rendering, on the second it will show correct data.
I need point where I'm sure that I have correct data.
...where var a = this.props.somethingFromState; will be assigned correctly.
Is render method best place and what is best practice for doing this in general. Thanks.
There are a couple of questions here.
With respect to where to load data, componentDidMount is indeed the correct place to call ajax methods and load data as suggested by the facebook docs.
In terms of whether or not to then pass that data down to child components via props, I like to follow Dan Abramov's (the author of redux) guid on presentational vs container components. In short, try to have a container component that loads your data and does all the logic, and then pass whatever is necessary down to presentational components via props, making them pure functions if possible.
In terms of when you will have the correct data, check the React lifecycle docs above. You will see that the constructor fires, then componentWillMount, then render, then componentDidMount. So if your ajax call gets the data in componentDidMount, you will have called render first, resulting in no data being loaded on the already mounted component. Most people solve this by putting a spinner until the data has finished loading from ajax. A simple if statement should accomplish this
I know I can pass props while rendering a component. I'm also aware of the getInitialState method. But the problem is, getInitialState isn't quite helping because my component doesn't know it's initial state. I do. So I want to pass it while I'm rendering it.
Something like this (pseudo-code):
React.render(<Component initialState={...} />);
I know I could use a prop to work as the initial state but this smells like an anti-pattern.
What should I do?
EDIT FOR CLARITY
Imagine I have a CommentList component. By the time I first render it, the initial state corresponds to the snapshot of current comments from my database. As the user includes comments, this list will change, and that's why it should be a state and not props. Now, in order to render the initial snapshot of comments I should pass it to the CommentsList component, because it has no way to know it. My confusion is that the only way I see to pass this information is through a props which seems to be an anti-pattern.
Disclaimer: Newer versions of React handle this on a different way.
Only permanent components might be able to use props in the getInitialState. Props in getInitialState is an anti-pattern if synchronization is your goal. getInitialState is only called when the component is first created so it may raise some bugs because the source of truth is not unique. Check this answer.
Quoting documentation:
Using props, passed down from parent, to generate state in
getInitialState often leads to duplication of "source of truth", i.e.
where the real data is. Whenever possible, compute values on-the-fly
to ensure that they don't get out of sync later on and cause
maintenance trouble
You can still do:
getInitialState: function() {
return {foo: this.props.foo}
}
As they will be the default props for your app. But as long as you are using a prop to set a value that presumably won't change, you can use the same prop inside of the render function.
<span>{this.props.foo}</span>
This props won't be modified, so no problem using it each time the render is called.
Edited answer:
In this case your initial state should not be a prop, should be an ajax call which populates the comment list.
To quote the React docs:
Using props, passed down from parent, to generate state in getInitialState often leads to duplication of "source of truth", i.e. where the real data is. Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble
And:
However, it's not an anti-pattern if you make it clear that synchronization's not the goal here
So if your props include a value and an initialValue, then it's clear that the latter is for initialization, and there's no confusion.
See the React docs for code examples.
If you know the state then I would tend to argue that the component you are rendering is not really in control of it. The idea in React is that any particular piece of state lives in only a single location.
After seeing the other answers, and studying a little bit about it, I've come to this conclusion:
If you are rendering React in the client (compiled or not), which is the default approach, you should try to make an extra Ajax call from inside your component to get the initial state. That is, don't use props. It's cleaner and less error prone.
However, if you are rendering in the server (Node.js or ReactJs.NET), there's no reason to make this extra Ajax call for each request.. Besides, it's not SEO friendly. You want the complete page to come as the result of your request (including data). So, as #RandyMorris pointed out, in this case it's ok to use props as the initial state, as long as it's exclusively the initial state. That is, no synchronization.
I'm using React for some client-side components. In some cases the components do not know their initial state, so I need a way to render the component and provide it with an initial state, externally.
renderComponent has a callback method:
ReactComponent renderComponent(
ReactComponent component,
DOMElement container,
[function callback]
)
Apparently:
If the optional callback is provided, it will be executed after the
component is rendered or updated.
Which is fine, but if I call setState in that callback, you will still see the initial (wrong) rendering for a split second before the component re-renders itself.
So my question is, can I do this:
var myComponent = React.renderComponent(...);
myComponent.setState({...});
...Safely? Can I presume that renderComponent has at least created the backing instance of the component in a synchronous fashion, so that there's something there to call setState on?
This pattern seems to work in my casual tests, using a localhost server, but I'm wondering if this is somewhat akin to using JS to modify the DOM without waiting for the ol' document-ready signal (i.e., prone to inconsistent behavior).
On the other hand, I could pass in a default state object as a prop, and then build the component so that it checks for that prop and populates its own state within componentWillMount or somesuch. Would this be more within the bounds of The React Way?
On the other hand, I could pass in a default state object as a prop, and then build the component so that it checks for that prop and populates its own state within componentWillMount or somesuch. Would this be more within the bounds of The React Way?
Yes. State should be treated like private instance variables for a component; you should never ever access them from outside the component, but just as it makes sense to pass options to an object constructor, it can make sense to specify some parts of the initial state of a component in props. React's uncontrolled components (with defaultValue) are an example of this sort of pattern.
When possible, it's usually nicer to keep the state stored higher up and prevent it from getting out of sync, much like React's controlled components. You can do this by making your component take an onChange callback that you then use to update your app's source of truth.
One other note: You should generally use getInitialState instead of componentWillMount; using the latter is currently allowed but may be deprecated in the future.