useReducer in sub-components without additional render? - javascript

I have a dashboard app that processes data streams and user actions via useReducer and immer to update the state. These updates are available when React is ready to render.
I would like to invite others to make their own dashboard widgets for my app. These widgets would be driven by the derived state from the dashboard's reducer.
Some complex widgets might want to also useReducer locally. They might have their own local data streams and inputs. Herein lies a design problem - widgets that useReducer will be one render behind the rest of the dashboard!
In my understanding, this is because output from the dashboard useReducer is only available just before a render, which means widgets driven by this data that want to useReducer locally must update via useEffect and thereby wait another render to draw their state.
Possible solutions:
"lift state up" into the dashboard, but this breaks a clean
separation of interests - the state of one widget is not relevant to
the other widgets. It will make maintenance a chore and cumbersome.
useMemo in widgets to wrangle and process data before
rendering. To ensure state is not lost, I could also have useMemo
update and return a value initially generated by useRef. This seems... like an anti-pattern.

Related

Can componentDidMount share data between pages?

I am still learning React and I apologize if this is a stupid question. I am currently planning about the architecture of my simple App.
I am using Next.js for this project
I have a component that calls the third party API for data every 5 seconds. The data is shared among all pages in the app.
If the component that is fetching the data is not on the main/home page. Are there anyways for homepage to get the data it needs from another page?
For example [Below are all pages]
index.js // Plain simple page that displays current weather and top music
http://localhost:3000/
weatherforecast.js //Using componentDidMount every 5 seconds to fetch Weather Data
http://localhost:3000/weatherforecast
musicplaylist.js //Using componentDidMount every 5 seconds to fetch Weather
http://localhost:3000/musicplaylist
The data shown in homepage has to be refreshed every 5 seconds if there are changes to the following data in weatherforecast.js and musicplaylist.js
I had this in mind but I have a feeling that it's not the right way to do it.
In the Homepage.js, include WeatherForecast and MusicPlaylist components to fetch the data. If this is the case, it seems like I am repeating the same principle in every page.
I found out about Redux which store states as a global object. But how does the state know when to update. But before we getting to state, I am still not sure if components on another page can fetch the data without the user accessing the page.
Thanks for reading this question.
For a pure React solution, you need to utilize other lifecycle methods available for React. componentDidMount is a good spot for making API requests, so you're in the right place to start. However, componentDidMount occurs only once, right after the componentWillMount and after the DOM is ready with a complete render of the component. Setting your API call to run at a set interval will not trigger a rerender of the component, no any of it's sub components. Instead, use componentWillRecieveProps to add your interval request logic. After each interval completes, run setState with the new data from the request to update the default state defined in your constructor. As a bonus step to improve performace, follow up with function that returns a bool in componentShouldUpdate. This way you can strictly define how and when and what is causing any and all component re-rendering.
Redux is an excellent solution to take care of what you want to do. Personally always use it in my React projects to manage state. Using Redux, you could make your API calls still occur in componentDidMount, however the call can hook into your Redux store and update your initial state. The frees you up from have to worry about the local state of your component and how to go about conditionally rendering everything else in your app. Plus Redux abstracts other functions you need, like re-running your fetchToAPI in certain intervals, into their own source (known as Action Creators). Action Creators hook directly in the Redux store so that when one is used, the resulting state diff is passed to Redux's Reducers, which in turn update the application global state. Then all that needs to be done is to have all of your components that need re-rendering on global state change to listen for state changes that occur in the Redux store and conditionally re-render based on the diff of the store from prevState => newProps. This can be setup fairly easy using the boolean check in componentShouldUpdate.
Hope this helps! Cheers.
Redux passes the data throughout the connected components via prop, given that a component is mounted whenever it receives new props a new render cycle is initiated so it will reflect your changes, moreover if you dont want to use Redux you can try using the new context api which is easy to implement and will also be suitable for your solution here is a tutorial on how to use it
To pass data between pages in next.js you will have to use Redux. The idea of Redux is to have a single source of truth. In redux you update the state by calling actions. To update redux state you have to create something called action creators which dispatches action to update the state.
Answer to your question as to if components on another page can fetch data without the user accessing the page is that they do not need to access the data. The components are mounted only when they are accessed, so it will fetch the data when they are mounted.
Regarding the state change notification, refer to below image, and hopefully it is worth one thousand of words:
Original article here.

How to Handle UI State in Redux/React - Redux-UI?

I am researching into what is the best way to store the UI state, Should I use something like Redux-UI (https://github.com/tonyhb/redux-ui) to store/manage the UI state? or should I create my own actions/reducers for the UI?
Also...
when I have stored the UI state, how do I make sure if the browser is refreshed, I still have exactly the same state of the page? Just as a normal web page would including Data taken from the server.
I have Redux with thunk middle wear implemented and a store. I have worked with React for the past couple of months thus far.
Thanks!
Quinton
Our team has spent some days on this. The reasons we want UI states, instead of putting those states to Redux's state tree, can be:
Those UI states are only relevant to a very small number of components. But yet sometimes we need to share those states amongst them. For example, a Button to control a Modal, they both need to read/write the 'isModalOpen' state.
Those states are not data, they are UI preference and it is fine to reset them to the default upon component unmount. Persisting them in the single Redux store sounds like polluting the state tree.
We tried:
Creating a separate redux state tree just for UI.
Add a main branch, say 'state.UI' for all 'UI' states.
However, all these involve having to use/implement custom middleware, actions and reducers. Hard.
At the end, I made react-provide-state. It works really well. The only drawback of it is your can not easily see the ui states like states in Redux tree in browser console. And you can only update states through UI (user action event callbacks). That's fair, it is UI states we are talking about.

Using Redux's store.getState() and store.dispatch() to make changes without subscribing in React?

I watched the Getting Started with Redux series and am working through modifying my existing React code to use Redux. However, I've run into a dilemma that I can't seem to find any answers for: I want to modify the store data (which many of my React components will use) on particular events such UI interaction, but I don't want any UI components to subscribe to every change made to the store.
Can/should I instead make a separate .js file with functions that can access the store directly to call .getState() and .dispatch() which my UI components can import and call when needed, instead of subscribing to the store themselves?
Or am I fundamentally misunderstanding something and subscribing to the store would have exactly the same effect? I'm aiming to optimize speed; that's why I switched to Redux.
I want to modify the store data (which many of my React components
will use) on particular events such UI interaction, but I don't want
any UI components to subscribe to every change made to the store.
Checkout react-redux, it's the official binding for react and redux apps. It provides a way to subscribe specific components to redux and only listen for the changes that you are interested in. On top of that it also implements various optimisations to avoid unnecessary re-renders.
Can/should I instead make a separate .js file with functions that can
access the store directly to call .getState() and .dispatch() which my
UI components can import and call when needed, instead of subscribing
to the store themselves?
You can do anything you like, but don't be surprised if it becomes unmaintainable after a while.
Or am I fundamentally misunderstanding something and subscribing to
the store would have exactly the same effect?
Yes, you could use react-redux and only subscribe to parts of the store that you care about.
I'm aiming to optimize speed; that's why I switched to Redux.
Not sure what your particular situation is / was, but in general the point of redux is to provide a predictable and manageable way of maintaining an applications state - it doesn't directly speed up anything.

Flux and application state

I'm a bit confused about the Flux architecture, especially about the following statement:
Application state is maintained only in the stores, allowing the
different parts of the application to remain highly decoupled.
I have a component which must have a state. My question is, if I want to use Flux in my application, should this state live in the stores or inside the component? Notice that this state is not data from an API.
Also, if an user performs an action, should the component manage that action or an action creator?
A component gets its initial state from the store, but whenever the store emits a change, the state of the component is updated.
The tutorial on tylermcginnis.com broke it down quite well for me: http://tylermcginnis.com/reactjs-tutorial-pt-3-architecting-react-js-apps-with-flux/

How to handle non-view-altering actions in Flux & React.js

In Flux every action should be handled by the dispatcher.
What about an action that doesn't alter the view or the markup, such as "scroll this element into view"? What is the "Flux-way" of handling such a scenario? To by-pass the dispatcher? Or to handle it in the dispatcher without involving the stores or the components?
Flux is really more about application state management, and is not at all about the details of what components are rendered in the view. That's the domain of React. Flux simply assumes you have some kind of reactive view layer -- usually that's React.
Application state is not the same as component state. Application state is something that needs to be known in multiple components. For component state, React's this.state is perfectly adequate. An input component is a good example of something that might need this.
So in your case, if only one component needs to know the scroll position, there may not be a good case for moving that state to a Flux Store. But as soon as that needs to be known in multiple components -- especially components in different branches of the tree -- you probably want that state being managed in a Store.
The other issue your question raises is the role of Flux Actions. A Flux application always uses Actions as the origin of the data flow. There are a lot of good reasons for doing this: stable application state, keeping the app resilient to new features, keeping it easy to reason about, undo history, reconstitution of application state, stateless view components, etc.
Occasionally people want to write as little code as possible and they use a callback passed between components to change this.state in the parent component instead of dispatching a new action to go through the Flux data flow. I find this to be mixing the view and state management layers of an application, and while expedient, this can lead to a lot of headache. It isn't very flexible in the long run, because now the state is coupled to these few components. Building up a Flux data flow from the start is much simpler in the long run, and much more resilient to new features. That said, it also requires more investment in code up front.
If your app doesn't need to know about scrolling (seems rare that it would), there's no need to fire an action. Since Flux is really there to handle data flow (and subsequent changes based on that data flow), it doesn't need to know about every action that occurs.

Categories

Resources