why components render when use `setState` to store new value? - javascript

In react, we commonly use the useState hook to store data. We don't update the state directly, because the component doesn't re-render in this way. Now my question is, How did setState trigger the rendering under the hood?
A common concept can be setState call the rendering. But I think maybe there is something else. (something global object or state obj manipulation, something like this).
I don't understand how to setState trigger rendering under the hood. If anyone can explain it, it will be very helpful for me including others.

Related

What's the reason for not getting the variable I'm expecting in the functional component?

I'm familiar with useState hook for storing variables that change and need to reload the component. Are variables not local to each function call? For example, I have a functional component that I passed ticket information to. I take that information store it in a variable and pass it to another screen. That component is render in a flat list depending on which one is called I want to store that value and pass it to another screen. My problem is, that value is getting stored in the local object but only the value of the last item rendered not the one pressed. Here is my code:
If I save ticket from params, update it with the "siteCode", and pass it in the params of the onPress event, I don't get the results i'm looking for. If i pass siteCode outside of the custom object I get the results I'm looking for. I just want to understand what I'm missing here. Do i still need to use the useState hook even though i'm not looking to render the component again? Thanks
You are breaking the contract, so unfortunately you get whatever you get. And since it's not a supported use case you sadly can't expect it not to change in different React versions either.
React expects a pure functional component to be, well, a pure, functional, component (referentially transparent, no side effects). You are mutating your props, which as I said is not supported (this seems to come up a lot on github issues on the React repo).
In ye olden days, if your component was not pure you used a class. Now we have hooks, but the hook is essentially a clever workaround: because React knows about the hooks you don't violate the functional component contract. But that doesn't mean anything goes, if you have a side effect (like mutating an object defined elsewhere) then you need to put it in a hook or screwy things will happen.
N.B. even in a class, or even outside of React entirely, it's rarely (never?) a good idea to mutate the parameter to a function unless that mutation is the only thing the function does.

What's the difference between React Context API & Hooks?

As i understand it, they both deal with state. Hooks seem to be more internal to a components state, while the context api seems to solve the problem of prop drilling, creating a more global state? Is this false? What am I missing?
Thanks a lot!
As I understand, they have completely different use cases. Context allows you pass a value deep into the component tree, where the value could be any kind of prop, say, a color. By using context in this way, you avoid having to do props.theme on every component that needs a theme color passed to it.
Hooks, on the other hand, replace the need for classes; instead you create a function and useState enables you to pass in variables. I.e. Hooks allow you to take a React function component and add state to it, and apply lifecycle methods like componentDidMount and componentDidUpdate. This is useful because if you find your function requires state, you don't need to refactor it into a class, you can just add Hooks. :) Of course this choice is contentious among developers though.

call forceUpdate() on component when redux state updates

I have an issue with redux state being updated successfully, but react component not re-rendering, after some research I believe [forceUpdate()][1] can solve my issue, but I am unsure of correct way to implement it i.e. after redux state updates. I tried looking up examples on github, but had no luck.
As others have said, forceUpdate() is basically a hack. You get updates for free whenever the props and state change. React and Redux work seamlessly together, so avoid any such hacks.
If your Redux state is updating correctly and your React view isn't, then it's most likely that you're not updating in an immutable fashion. Check your reducers.
It is possible that your issues is that the state you are updating is not a top level property. react calls a "shallowEqual" method to tell whether the props have updated. This means all top level properties, but if you are changing a deeper property and all the top level ones are the same then you will not rerender.
I'm not sure if this would be the case with redux maybe it's doing something more sophisticated but I know that is the workflow in react. It's worth taking a look.
That's not the solution you want.
Without looking at your code, it's impossible to tell what's actually wrong, but forceUpdate is not the solution. React will re-render if new data is placed in the state or props. If you're not re-rendering, it means you're data isn't getting all the way through.
Redux already doing forceUpdate with connect decorator. Maybe you miss this point in your component. This behaviour is explained on the Usage with React section of official documentation.

ReactJs: How to pass the initial state while rendering a component?

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.

ReactJS - Can I call setState immediately after renderComponent?

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.

Categories

Resources