Make snapshot of page state in Next.js - javascript

I faced with some problem while developing Next.js application. It is rather an architectural issue.
I want to switch between routes, but keeping all the states on the page so that I can return to page without loosing it's state. I understand that I need to use initalProps at the top level. But this is only suitable for simple cases. Let's take an example where there're hundreds of states on a page with different levels of hierarchy. Is it possible to make a snapshot of all page states?
I look towards memo from React. Also, I think Redux would help me, but I don't use it in the application at all and it's one more dependency. Perhaps this can be solved using the Context Api.

If you have global state that you need to share between different pages and the state is simple you can use Context API, the Component needs to be wrapped by the ContextProvider in the custom app component in _app.js.
The pseudo-code might look something like this for your use case,
// context and the provider component
export const MyContext = React.createContext();
export const MyCtxProvider = ({ children }) => {
// state logic
return (
<MyContext.Provider value={/* state value */}>
{children}
</MyContext.Provider>
)
}
in _app.js
import App from 'next/app'
import { MyCtxProvider } from './path-to-myctxprovider'
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return (
<MyCtxProvider>
<Component {...pageProps} />
</MyCtxProvider>
)
}
}
export default MyApp
Here is an example from nextjs repo that uses context API to share state between pages.
But if your global state is somewhat complex i.e. you want to keep both server state(fetched data from a remote API) and UI state in the global state, you might wanna use a state management system like redux in this case. There are a lot of examples in the nextjs repo showing how to implement it. You can start from there.

As far as I understand, it will be an architectual problem. For global state management you need to use e.g: Redux, graphql, ContextAPI, or give a global state to your app in pages/_app.js. That will wrap your pages, and provide a cross pages state.(You can modify, and reuse that)
Opnion: Implement Redux, if it"s really need. (for large amount of data in the state). Because it"s easier to implement, then remove it. Other case: Use the inbuild ContextAPI, or the pages/_app.js state handler till it"s fit for your application.

Related

Does mapStateToProps in component file make sense?

I'm learning Redux and so far I find it really, really confusing.
In all tutorials I've seen so far, the mapStateToProps function is included in the component file itself, for example (I removed irrelevant parts if the snippet):
import React from 'react';
import { connect } from 'react-redux';
import CartItem from '../cart-item/cart-item.component';
const CartDropdown = ({ cartItems }) => (
<div>
{cartItems.map(cartItem => (
<CartItem key={cartItem.id} item={cartItem} />
))}
</div>
);
const mapStateToProps = ({ cart: { cartItems } }) => ({
cartItems
});
export default connect(mapStateToProps)(CartDropdown);
I don't get it how does it make sense to put mapStateToProps in the component file, as it makes my component dependent on the Redux state. Why all the hassle with passing it to props if we only use the Redux state?
Bonus commentary: I'm not gonna lie, Redux gives me a bit of a headache so far. I don't understand why the boilerplate is so huge. Adding any new Redux state property looks like a chore. Does it only make sense in huge apps in general? The idea of having actions, reducers, dispatchers, mappers, stores and a provider for mostly simple tasks is tough.
Perhaps you should understand the purpose of redux, why are you using redux in the first place. By default ReactJS providing React hooks or setState for you to manage state, which works great on component level, but as soon as your apps grows, most likely there are more than one components needed to access the same state.
Solely because of the problem above, you have many options available to solve that. Redux, React Context, Mobx. All of them are being categorized as State Management Library. Definitely they all have their pros and cons and I'm not here to push to any one of the library, you can easily google around to see the comparison between them and select base on your use case.
Now back to your question if mapStateToProps make sense, it totally is, abstract away all the complexity, how do a component receive external data? It's only via props

Is it right way to pass Redux store via React Context in Root Component?

I'm scaffolding a large scale React application. In fact it is a advanced level of admin panel, I wanna use Redux for handling the global state of application and Redux Saga for asynchronous actions.
Few days ago I saw an article in medium, Which it's about new React Context API, It's awesome and useful.
Also I saw a useful Stack Overflow question about using React Context, Here is about React Context vs React and my situation is some different.
In my case I wanna use Redux for controlling global state of application like login, global data and etc, and passing these data to all of components tree with React Context, is it a right way? is there a better way to leverage?
react-redux internally uses context to pass on the data to the component. With redux you can make use of connect and supply the data to the component that needs it. Its not necessary to use context for this purpose
For instance you have a Admin component, you can pass state values to it like
import { connect } from 'react-redux';
class Admin extends React.Component {
...
}
const mapStateToProps = (state) => {
return {
isLoggedIn: state.isLoggedIn
}
}
export default connect(mapStateToProps)(Admin);
You can learn more about it here

React Multiple Higher-Order Components

I'm just discovering the amazing benefits of using HOC in my react projects.
My question is there any performance hit for calling multiple HOC functions on a component?
Example
export default withState(withLabel(withTheme(MyComponent)))
This will of course only render one component, however looking at my react dev tools i can see the outputted HOC components three levels deep. Is this something to be wary of or is there a better approach to calling multiple HOC on a component?
Your syntax is equivalent to doing:
<StateProvider>
<LabelProvider>
<ThemeProvider>
<MyComponent />
</ThemeProvider>
</LabelProvider>
</StateProvider>
The performance hit will come from how these HOC are implemented. You would probably have to look at each of them.
Example:
Theme Provider HOCs usually store a bunch of colors and variables in the React context. So using only one at the very root of your App is enough.
One could imagine that your LabelProvider simply adds an extra span before your component, in which case there is little to worry about
StateProviders like redux usually inject props in the component just below them so you don't really have a choice but to use them whenever you need state objects.
In conclusion, there are no hard rules. Your main focus should be on understanding what these HOC do and to try to limit unnecessary re-renders of your app.
I wouldn't use that. It's complicated to understand where the props come from, when you are looking at your MyComponent component. There are much more downsides using this pattern. Anyway if you decided to use HOCs use it in a right way e.g.
const withDetails = Component => {
const C = props => {
// do something
}
// assign display & wrapped names - easier to debug
C.displayName = `withRouter(${Component.displayName))`
C.WrappedComponent = Component;
return C;
}
Instead of using HOCs i suggest looking at render props react pattern. It's well explained in a Use a Render Prop! article by Michael Jackson (react-router creator).
Hope it makes sense.

What are differences between redux, react-redux, redux-thunk?

I am using React + Flux. Our team is planning to move from flux to redux. Redux is very confusing for me coming from flux world. In flux control flow is simple from Components -> actions -> Store and store updates back components. Its simple and very clear.
But in redux its confusing. There is no store here, yes there are some examples without using store. I went through several tutorials, it seems everyone has their own style of implementation. Some are using Containers and some are not. (I don't know this Containers concept and not able to understand what mapStateToProps, mapDispatchToProps does).
Can someone clearly explain how control flow happens in redux ?
What are roles of components/containers/actions/action creators/store in redux ?
Difference between redux/react-redux/redux-thunk/any others ??
It would be very helpful if you can post links to any simple and precise redux tutorials.
Can someone clearly explain how control flow happens in redux ?
Redux has (always) a single store.
Whenever you want to replace the state in the store, you dispatch an action.
The action is caught by one or more reducers.
The reducer/s create a new state that combines the old state, and the dispatched action.
The store subscribers are notified that there is a new state.
What are roles of components/containers/actions/action creators/store in redux ?
Store - holds the state, and when a new action arrives runs the dispatch -> middleware -> reducers pipeline, and notifies subscribers when the state is replaced by a new one.
Components - dumb view parts which are not aware of the state directly. Also known as presentational components.
Containers - pieces of the view that are aware of the state using react-redux. Also known as smart components, and higher order components
Note that containers / smart components vs. dumb components is just a good way to structure your app.
Actions - same as flux - command pattern with type and payload.
Action creators - DRY way of creating actions (not strictly necessary)
Difference between redux/react-redux/redux-thunk/any others ?
redux - flux like flow with a single store, that can be used in whatever environment you like including vanilla js, react, angular 1/2, etc...
react-redux - bindings between redux and react. The library offers a set of react hooks - useSelector(), and useStore() to get the data from the store, and useDispatch() to dispatch actions. You can also use the connect() function to create HoCs (higher order components), that listen to the store's state changes, prepare the props for the wrapped component, and re-render the wrapped components when the state changes.
redux-thunk - middleware that allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. Used mainly for async calls to api, that dispatch another action on success / failure.
It would be very helpful if you can post links to any simple and
precise redux tutorials.
Redux official docs
Getting Started with Redux
Building React Applications with Idiomatic Redux
Presentational and Container Components
To answer you title question:
What are differences between redux, react-redux, redux-thunk?
redux: main library (independent from React)
redux-thunk: a redux middleware which
helps you with async actions
react-redux: connects your redux store with ReactComponents
redux: Library for managing application state.
react-redux: Library for managing React application (redux) state.
redux-thunk: a middleware for logging, crash reporting, talking to an async API, routing etc...
To my mind, Redux, is still a little confusing for the first time of studying this library, and need some time to understand and start to use one. Even if you use Redux Toolkit - the latest library (from Redux authors) - it also has some tricky moments which might be unclear from the beginning.
I`m using Master-Hook.
Redux , react-redux , redux-thunk , reselect are already installed in the library and you need to follow the steps.
1st step: Create ‘src/hooks.js’ file
import MasterHook from 'master-hook'
export const useMyHook = MasterHook({
storage: "myStorage",
initialState: {
myName: 'Vanda',
},
cache: {
myName: 10000,
}
})
You create your component and export it (useMyHook)
Set the initial State (initialState:...)
Set how long the value need has to stay cached in ms (cache:...)
2nd step: Add Provider to src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import MasterHook from 'master-hook';
ReactDOM.render(
<React.StrictMode>
<MasterHook.Provider>
<App />
</MasterHook.Provider>
</React.StrictMode>,
document.getElementById('root')
);
Import MasterHook
Wrapp your file with MasterHook.Provider
3rd step: Use your hook in src/App.js
import logo from './logo.svg';
import './App.css';
import { useMyHook } from './hooks'
function App() {
const { myName, setMyName } = useMyHook()
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
My name is {myName}
</p>
<a
onClick={() => setMyName('Boris')}
className="App-link"
>
Set my name to 'Boris'
</a>
</header>
</div>
);
}
export default App;
Import your hook
useMyHook
Declare your hook
const { myName, setMyName } = useMyHook()
Use it in your code
{myName}
and
{()=>setMyName('')}
Delete href attribute to prevent it from changing the page. setMyName action is created automatically.
No need to connect to the store. It’s already connected.
4th step: Run your project!
npm run start
That`s it :)
bellow image demonstrates how data flow in redux :
how the data flows through Redux?
Advantages of Redux are listed below:
Predictability of outcome – Since there is always one source of truth, i.e. the store, there is no confusion about how to sync the current state with actions and other parts of the application.
Maintainability – The code becomes easier to maintain with a predictable outcome and strict structure.
Server-side rendering – You just need to pass the store created on the server, to the client-side. This is very useful for initial render and provides a better user experience as it optimizes the application performance.
Developer tools – From actions to state changes, developers can track everything going on in the application in real-time.
Community and ecosystem – Redux has a huge community behind it which makes it even more captivating to use. A large community of talented individuals contribute to the betterment of the library and develop various applications with it.
Ease of testing – Redux’s code is mostly functions which are small, pure and isolated. This makes the code testable and independent.
[Organization][2] – Redux is precise about how code should be organized, this makes the code more consistent and easier when a team works with it.

When should I add Redux to a React app?

I'm currently learning React and I am trying to figure out how to use it with Redux for building a mobile app. I'm kind of confused on how the two are related/usable together. For example, I completed this tutorial in React https://www.raywenderlich.com/99473/introducing-react-native-building-apps-javascript, but now I want to play around with adding some reducers/actions to that app and I am not sure where those would tie in with what I've already done.
React is a UI framework that takes care of updating the UI in response to the “source of truth” that is usually described as a state “owned” by some component. Thinking in React describes the React state ownership concept very well, and I strongly suggest you go through it.
This state ownership model works well when the state is hierarchical and more or less matches the component structure. This way the state gets “spread out” across many components, and the app is easy to understand.
However sometimes distant parts of the app want to have access to the same state, for example, if you cache fetched data and want to consistently update it everywhere at the same time. In this case, if you follow the React model, you’ll end up with a bunch of very large components at the top of the component tree that pass a myriad of props down through some intermediate components that don’t use them, just to reach a few leaf components that actually care about that data.
When you find yourself in this situation, you can (but don’t have to) use Redux to “extract” this state management logic from the top-level components into separate functions called “reducers”, and “connect” the leaf components that care about that state directly to it instead of passing the props through the whole app. If you don’t have this problem yet, you probably don’t need Redux.
Finally, note that Redux is not a definitive solution to this problem. There are many other ways to manage your local state outside the React components—for example, some people who didn’t like Redux are happy with MobX. I would suggest you to first get a firm understanding of React state model, and then evaluate different solutions independently, and build small apps with them to get a sense of their strengths and weaknesses.
(This answer is inspired by Pete Hunt’s react-howto guide, I suggest you to read it as well.)
I've found that the ideal path for adding Redux to an application/stack is to wait until after you/app/team are feeling the pains that it solves. Once you start seeing long chains of props building up and being passed down through multiple levels of components or your finding yourself orchestrating complex state manipulations/reads, that could be a sign that your app may benefit from introducing Redux et al.
I recommend taking an app that you've already built with "just React" and see how Redux might fit into it. See if you can gracefully introduce it by plucking out one piece of state or set of "actions" at a time. Refactor towards it, without getting hung up on a big bang rewrite of your app. If you're still having trouble seeing where it might add value, then that could be a sign that your app is either not large or complex enough to merit something like Redux on top of React.
If you haven't come across it yet, Dan (answered above) has a great short-video series that walks through Redux on a more fundamental level. I highly suggest spending some time absorbing pieces of it: https://egghead.io/series/getting-started-with-redux
Redux also has some pretty great docs. Especially explaining a lot of the "why" such as http://redux.js.org/docs/introduction/ThreePrinciples.html
I have prepared this document to understand Redux. Hope this clears your doubt.
-------------------------- REDUX TUTORIAL ----------------------
ACTIONS-
Actions are payloads of information that send data from your application to the store. They are the only source of information from the store. You can send them
only using store.dispatch().
Example-
const ADD_TODO = 'ADD_TODO'
{
type:ADD_TODO,
text: 'Build my first redux app'
}
Actions are plain javascript object. Action must have a [ type ] property that indicates the type of action being performed. The type should be defined as a string constant.
ACTION CREAToRS-----
---------------- ---- Action creators are exactly the function that creates action
It is easy to conflate the terms - action and action creator.
In redux action, creator returns an action.
function addToDo(text) {
return {
type: ADD_TODO,
text
}
}
to initialte dispatch pass the result to the dispatch() function.
dispatch(addToDo(text));
dispatch(completeToDo(index))
Alternatively, you can create a bound action creator that automatically dispatches.
cosnt boundAddTodO = text => dispatch(addToDo(text));
now you can directly called it
boundaddTodO(text);
The dispatch() functionn can be directly accessed from store.dispatch(). but we
access it using a helper connect() method.
Actions.js.....................
Actions...........
exports cosnt ADD_TODO = 'ADD_TODO';
exports cosnt TOGGLE_TODO = 'TOGGLE_TODO'
Actions Creators
export function addToDO(text){
return {
type: ADD_TODO,
text
}
}
.........................REDUCERS..................................
Reducers specify how the applications state changes in response to actions sent to the store.
Designing the state shap
In redux all the application state is store in single object. You have to store some data as well as some state.
{
visibilityFilter: 'SHOW_ALL',
todos: [
{
text: 'Consider using redux',
completed: true
},
{
text: 'Kepp all the state in single tree'
}
]
}
Handling Actions
---------------- the reducers are the pure functions that take the previous state and action, and return a new state.
(previousState, action) => newState
We will start by specifying the initial state. Redux will call our reducers with an undefined state for the first time. this is our chance to return the state of our app.
import { visiblilityFilters } from './actions';
const initialState = {
visibilityFilter: VisibilityFilters.SHOW_ALL,
todo: []
}
function todoApp(state, action){
if(typeof state == 'undefined'){
return initialState;
}
// dont handle other cases as of now.
return state;
}
you can do the same using ES6 way of handling the JS
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
}
................................. STORE...................................
The store is a object that brings them together. the store has following responsbility
hold application state
allow access to state via getState()
Allow state to be updated via dispatch()
Register listerneres via suscriber(listener)
Note. use combineReducers() to combine several reducers into one.
const store = createStore(todoapp); // the todoapp are the reducers
This is how redux works. A action is dispatched from any compoenent or view. Action MUST have "type" property and may be any property which holds information of action happened. The data passed in action, could be relevant to different reducer, so same object get passed to different reducer. Each reducer takes/ make-out its part/contribution to state. The output is then merged and new state get formed, and the component which must be subscribed for state change event gets notified.
In above example, brown color has all 3 component RGB. Each reducer receives same brown color and they seperate out its contribution to the color.
Firstly, you don't need to add Redux to your application if you don't need it! Simple, so don't force yourself to include it in your project if you don't need it at all! But that doesn't mean Redux is no good, it's really helpful in large applications, so read on ...
Redux is a state management for your React application, think about Redux like a local store which track of your state as you go, you can access the state in any page and route you want, also compare to Flux, you only have one store, means one source of truth...
Look at this image to understand what Redux does first at a glance:
Also this's how Redux introduce itself:
Redux is a predictable state container for JavaScript apps.
It helps you write applications that behave consistently, run in
different environments (client, server, and native), and are easy to
test. On top of that, it provides a great developer experience, such
as live code editing combined with a time traveling debugger.
You can use Redux together with React, or with any other view library.
It is tiny (2kB, including dependencies).
Also as per documentation, there are Three Principles for Redux as below:
1. Single source of truth
2. State is read-only
3. Changes are made with pure functions
So basically when you need to a single store to keep track of anything you like in your application, then Redux is handy, you can access it anywhere in your app, in any route... simply using store.getState();
Also using the middleware Redux, you can do manage the state much better, there a list of handy components and middleware on official page of Redux!
Simply if your application gonna be big, with many components, states and routing try to implements Redux from start! It will help you on the way for sure!
When we write application we need to manage state of the application.
The React manages states locally within the component if we need to share the states between components we can use props or callbacks.
But as application grows it becomes difficult to manage states and state transformations.State and state transformations need to properly tracked in order to debug the applications.
Redux is a predictable state container for JavaScript apps that manages state and state transformations and is often used with React,
The concept of redux can be explained in following image.
When user triggers an action when user interact with the component and an action is dispatched to store then the reducer in the store accepts the action and update the state of the application and stored in the application wide immutable global variable when there is an update in store the corresponding view component subscribed to the state will get updated.
Since state is managed globally and with redux it is easier to maintain.
Having used Redux and personally finding it cumbersome, I found passing around an object to my components as a prop can be a much easier way to maintain state. Not to mention it's an easy way of making references to functions to call in other components. It can solve a lot of the cumbersome issues of passing messages between components in React, so it's a two for one.

Categories

Resources