I have a React app that takes the user through various steps. I want to have the ability to use the browser's "back" button to go back to a previous step. Now I'm thinking of using react-router to do this.
Currently, I am simply reacting to events and calling setState on my top-level component.
My question: Does all state have to be reflected in the URL, or saved into local storage? Or can I keep the component's state and just have react-router change some props on the top-level component? When I do that, do I risk loosing the component's state (e.g. because React doesn't identify the old and the new components)?
I want to have simple URLs like /step1, /step2... . These do not reflect everything that is going on in the app. Specifically, I don't need or want the ability to directly enter such an URL. There are also privacy concerns. I am happy with having the application's state in the main component's ephemeral state. In other words, my application's state is not a pure function of the route.
I want to mainly use react-router to make the back button act as a glorified undo / go to last step button, and only secondly to navigate to other components. Any idea or small snippet showing how to do that? Or is react-router not suited for this?
When React navigates from one component hierarchy to another (such as react-router links / history navigation) it only unmounts the components that do not exist in the new component hierarchy. State is only lost in unmounted components. If your state is properly stored at the top level which only goes through rerendering and not remounting, you should retain it.
Related
Most places suggest showing spinners or global modals at the top-level inside app component. Regardless of how we manage them, this would mean state change in the top-level component, which would then rerender and then all the children will re-render. Isint this more expensive than say just rendering the modal or spinner inside the component which needs it? even if it means repeating code. I mean we can live with some code repitition as long as we dont have to rerender our whole component tree. Maybe i am not very experienced with react and missing somehting fundamental here
In my opinion it just depends on the context. If you're loading the data that affect the whole app (auth info, feature flags etc.) the loader should be on the top level (since the whole app should actually refresh after the data loads).
On the other hand, you can add the loader modal side by side with the root of the actual component tree, so that it doesn't cause the whole view to rerender, it's all up to the design/requirements.
I'm doing a Chrome plugin for Facebook and I want to modify a post using external javascript. I can change the textContent of a span but the state is not changed and the Save button is not activated.
The html looks like that :
<div class="" data-block="true" data-editor="1477r" data-offset-key="a699d-0-0">
<div data-offset-key="a699d-0-0" class="_1mf _1mj">
<span data-offset-key="a699d-0-0">
<span data-text="true">test</span>
</span>
</div>
</div>
The component in React Developper Tools :
[
I profiled a change of the text and this is the result for a 6 ms timeline activating the save button.
There are ways to modify a React input but did not found ways for my problem :
https://github.com/facebook/react/issues/11488
https://github.com/facebook/react/issues/10135#issuecomment-314441175
How can you change a Facebook post and his state with external javascript?
What would you do?
That’s not possible, you can’t imperatively mutate a React element tree from outside the app. You’d have to declaratively render a tree, either by modifying Facebook’s frontend code (beware of legal ramifications) or implementing your own post UI.
While it's nearly impossible to change the state of React component from your plugin, nothing stops you from emulating user's input by sending keystrokes, mouse clicks etc. The only thing you need it to figure out - which DOM-element listens to these events (not necessary one of those 4 in you question).
About the possibility of direct state change: let's say the component you need to changes is a functional one. Then it has a form of
Component() {
const [state, setState] = useState(...)
...
setState(something)
...
}
so you need to somehow access the setState function of the component. But how? It's private to the function call. If you think that instead you can call the useState directly, then be aware that in another component it will return another setState. I have no idea what would happen if you'll call useState outside of a component, but surely it will not be able to guess which setState you want.
If you want you can check the source code of react-devtools to find out how you can dig out the state from the depths of React... but would you really want to try? And for what? The next time Facebook or React will be updated your code will definitely break.
I am new to React and a bit struggling with state in React and how and where we need to use it. So far, I found out that "If modifying a piece of data does not visually change the component, that data shouldn’t go into state". So, state is all about re-rendering the UI(I hope I am correct). So, the question I want to ask is Is it true that we use state only for re-rendering the UI only?, nothing else and nothing more?
You can use state in your class components. State is like private data of your component that may change by action made by user.
State is immutable. This means you can not change state directly in following way this.state.someVal = "smth". The only way to change state is using this.setState() method.
When you change state value React automatically re-renders your component without refreshing the page. In other words React.js reacts to your changes
State is an object that is directly tied to rendering the component. The reason why you can't change State directly with say this.state.foo='bar' is that React would have no way of knowing that it needed to re-render the component if you did that. Thus there is a setState method to change the state, which under the hood calls the render function of your component.
Therefore, if you have some data that has nothing to do with rendering the component, you don't want to put it into state, as setting its value will cause unnecessary renders to occur. If you're using class components, you can just put that data on the class directly: this.foo='bar'.
Basically yes! Two examples might be: A - holding a list of items (shopping list, or todo items) that are rendered directly to the UI, that are subject to change as the user adds and removes items. B - a value that determines whether or not you want something to show up on your UI, for example, you might have a state value called 'showNavbar' that is either true or false, depending on whether you want the user to see a navigation bar.
I hope that helps make sense of it in a basic way :)
We use the state for rendering the UI.
Also, I think the State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.
For this, We use the 'setState' method.
setState() is the only legitimate way to update state after the initial state setup
For a project, we want to have notifications visible throughout all views in the app.
The sidebar menu allows users to move between views, and is on the same level as the notification component and the websocket component react-stomp. The router is used to change the view on the next level depending on the selected menu item.
Our problem is that if a new message arrives, we need to pass it down to the view as props, and of course this triggers a re-render of the entire component.
Is there a way to avoid this rerender?
We would like to avoid redux, though we are aware it is a possible solution.
By default, if props changes react will trigger re-render. If you want to avoid rendering a componenet you can use the hook shouldComponentUpdate(nextProps, nextState)
Quoting React's documentation:
Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior.
For further reading visit their docs
Have you tried experimenting with react lifecycle event hooks ?
You could use REACT CONTEXT API if you want to avoid using a state manager like Redux or MobX
I have few React Components in my app which sends ajax calls. All works fine except one thing. I want to refresh the page when a particular component gets updated. So I used location.reload() in componentWillReceiveProps method. Though it works, unfortunately the whole page reloads whenever a component gets an update instead of just the component that has location.reload() code.
Why this is happening and how can I prevent / solve this?
Update and clarification: Thanks for the answers. I'm very much aware that state change re-renders the component. This is not a standalone React app and refreshing page is a requirement.
This react app is part of WP settings page which is tabbed one. One tab of settings is a react app. Upon enabling a button, corresponding tab should be visible and that needs page refresh (as it is not react, but WP backend code).
My question is If I add location.reload() in componentWillReceiveProps method of a single component, then why other components also refreshes page even though they don't have such code. Is componentWillReceiveProps a static method that is shared between all components? Why does other component state changes picks up location.reload() and refresh pages?
use a state variable and whenever you get any changes then setState which will only update your component instead of updating the whole page.
for more reference see this:https://reactjs.org/docs/react-component.html
wrap location.reload() with some condition (eg. if block) and choose that condition according to your component state change, don't write location.reload() directly because it will run for any state change that passed to that component.