Why is redux better than a simple object? - javascript

I am learning Redux. As I understand, Redux in React helps us to manage state of React app. But why can't I just use empty object to hold all necessary state changes?
For example, I have root component with two subcomponents.
<App>
<Label/>
<Button/>
</App>
Inside Label I have state {numb: 1} and one function, that increase numb
increase() {
setState(prevState => {
return {numb: prevState.numb + 1}
});
}
On top of this component I import Store.js file, that exports empty object, that I use to store all my change state functions.
import Store from './Store'
And in the constructor of Label, I just assign function from that component
Store.plusOne = this.increase
That helps me to import Store file inside Button component and use increase function to increase Label's numb property.
<button onClick={Store.increase}>Plus One to Label's numb</button>
So what is the point to use Redux, if I can store any state change function in a separate object?

I had the same feeling when I started with Redux a few years ago. "Man, this seems overly complicated". But then I realised while not using redux that I was doing the same things but less efficient and more error prone when doing things "manually".
Redux comes with a few powerful helper functions. The first one is connect which helps you to get those state properties into your components. You can literally connect your components to your state. You don't have to worry about anything else, change the state in a single place and watch the changes flow through your application.
Because you "plop" (yes, a technical term...cough) all the properties you need for that component from your state onto the props of your component you automatically get that the component refreshes when your state changes. Even while using pure functions or a PureComponent which might be very good for performance.
You can see it like this. If you want React + Redux to automatically reflow your application: use Redux. If you manually want to update a object and manually force your application to reflow, use a custom state object.
That being said, I think redux makes sense in bigger applications where multiple components depend on the same state. If you just have a single piece of data rendered in a single component or a demo app with a simple button click you might as well keep it simple with a small object.

Related

Redux simulated component update

What is the most efficient way in (functional) React to update a component when a variable changes value?
A piece of code somewhere in the program (over which I have no control) changes a variable e.g. an array in a "Redux" compatible way (i.e. a new reference is returned).
I would like to simulate Redux's useSelector without having to have to use Redux.
Updating the component means you need useState, Not sure what exatcly you are looking for, But if you want to update the component without much Props drilling, then i will suggest you to look into the Context-API on react.
This way you can have control like redux, without redux.
https://reactjs.org/docs/context.html

Can you bypass state management for simple objects? (global shared state)

Can you globally instantiate a class and that will be reliable on react-native? i.e.
// logs.ts
const instance = new Instance()
export { instance }
// something.tsx
const Component = () => {
instance.method()
...
}
If method were to increment a property by 1 would that property always have been incremented the number of times method was called throughout the project?
The primary benefit here is simplicity. For example, it's easier to define
class SomeClass {
constructor(properties){}
addProperty(key,value){ this.properties[key] = value }
}
than it is to do the equivalent in redux. Why don't people do the above more often?
Just changing the value on some object will not result in state changes/cause a component to re-render. You still need a state provider to have the state set to. If you want to change the state of that Provider you'll need to run setState (or dispatch and useReducer) which means you'll need to pass the dispatch of that function around to all of its children. As your app grows larger you'll definitely want to/need to useReducer and perhaps even several providers, you'll be re-implementing redux which is only about 200 lines of code anyway. So the question will become why did you re-implement redux which is such a popular library that most people know exactly how to use and there is plenty of documentation for, in favor of your homegrown version of redux which doesn't provide much additional value?
In redux a primary benefit is the tooling like redux-logger, redux-thunk, redux dev tools and time travel and others etc which allows you to replay the changes made or undo them. Sure it is easy to modify an object but using redux allows you to testably and consistently see how an object (the redux state) changes over time and undo them. You can test that action creators return the correct actions. You can separately test that given specific actions the reducer behaves as expected and replay that with mockStore. In short, using redux you get the enterprise version supported by a large community of experts who have helped improve and implement essentially the simple class that you demoed.
Although you can do this, it breaks away from the point of redux. Redux is meant to be a centralized state management store, and therefore, allow components to
access shared state from a single location and analyze shared states, because it comes from one place.
track history and actions taken to get state there
makes maintaining, debugging and collaborating on a codebase
much easier.
Doing the first option, all these benefits are lost.
That said, if you have multiple components in one file, and you want them all to share that same global state (not exporting it), using the class constructor to do so isn't a big deal, as long as the project isn't being worked on by other developers.
However, it would make more sense in that case to make an overall component class, and pass state down, as that is the point of React. Declaring a class outside and trying to manage state in the first way, would be a declarative approach, which is what React doesn't want developers to do (i.e there is a better way, like creating a hierarchy of components). That way, components re-render on a change in value, and no weird bugs arise

Redux: How do partial re-renderings work?

This question is about internals for partial re-renderings with React-Redux.
To explain what I mean, I will first introduce a very crude technique for managing state without any state management libary.
The technique uses a a huge "AppState"-object that is owned by the top-level App-component.
Suppose that this AppState holds not only state-properties, but also several callbacks that mutate those state-properties.
Furthermore, suppose that we use props to pass down this AppState throughout the entire component hierarchy.
Thanks to the ES6-spread syntax, passing a huge number of props can be done without a lot of boilerplate code.
In the top-level App-component, it will look like this:
<ChildComponent {...this.state} />
In all other components, it will look like this:
<GrandChildComponent {...this.props} />
It is important to note that the ES6-spread syntax does not actually pass the AppState-object. Instead, it extracts all the AppState-properties and passes them as separate props.
Now we should distinguish between top-level properties and nested child-properties of the AppState:
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (unless I use things like pure components).
However, if I change a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This leads to my final questions:
What is the render-performance of this crude approach in comparison to Redux?
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (because everything depends on the AppState).
If you mutate and use pure components then nothing will render, you change state by creating a new state object.
However, if I mutate a nested child-property of this AppState, then nothing will happen because React does not notice the property change.
This is only true if you mutate and components are pure.
What is the render-performance of this crude approach in comparison to Redux?
Prop drilling will re render the entire tree but branches that use state that didn't change won't re render if they are pure. Prop drilling is bad for maintenance because if you need to refactor grand child state logic you may need to refactor the whole tree or branch. But from a performance point it would not take a big hit provided that you use pure components and are careful when passing callbacks and not re creating them on every render (see useCallback).
How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?
React-redux useSelector or connect mapStateToProps are always called every time dispatch changed state and before rendering.
If the result is different than last result then react-redux will trigger render of the component. If the component gets props then a render could also be triggered because props change and mapstate/selector will be executed.
A connected component will observe state and render when the result of mapState or selector has changed. An example app with logs showing what react-redux will execute can be found here
For state management, you don't necessarily have to use Redux, if your use cases are small, maybe React Hook would be perfect for you.
For React rerendering matter, what I know is there are several strategies (useMemo, PureComponents) provided by React for managing and improve the performance. It really depends on how you manage your components.
One example is using PureComponent, even if you have a large state in your top-level app.js, if you manage the child components properly, they will not re-render if their receiving props haven't changed.

why do I need redux in react native?

I am trying to find out why do I need redux if RN already have state, I can use state as I want as action or change something.
So why would I need it?
Redux provides a "shared state" that every component can access. For example, you may have found that a parent component needs to be aware of the state of a child component. You can resolve this in React alone by passing down a method as props to the child but this isn't a pattern you want to be repeating again and again, especially as your component structure becomes more complex and hierarchical. Redux provides an elegant solution. For small apps though, it's probably not necessary.

How should child components in React communicate between each other in a clean and maintainable fashion?

I'm fairly new to React and I'm trying to understand a clean way for child components to communicate with each other.
In a simple component, I know that I can make use of props to pass data to child and callbacks for children to pass data back to parent component.
In a slightly more complex case, when I have multiple children components in a parent component, the communication between the children gets a little confusing. I'm not sure what I should do for children components of the same level to communicate with each other.
In my case, I decided that, maybe, I could use states. So I will have a state value in the parent component, and pass it on the children's props. Similarly, the callback handlers (called from the children component) in the parent component will help to set the states accordingly so that a state value gets passed on from one child to another through React's binding.
And a pseudo code could look something like:
//Inside Parent Component
constructor() {
//initialise state for the child components
this.setState({testList: []});
}
render() {
return (
<div>
<ChildA onSomething={this.onSomethingHandler} testList={this.state.testList} />
<ChildB onSomethingElse={this.onSomethingElseHandler} testList={this.state.testList} />
</div>
);
}
onSomethingHandler(evt):void {
if(blah.blah.blah) this.setState({testList: this.state.testList.splice().push(evt.value)};
}
onSomethingElseHandler(evt):void {
//Some other complex biz logic...
if(blah.blah.blah) this.setState({testList: this.state.testList.splice().push(somethingOtherStuffDueToLogic)};
}
//Inside ChildA Component
export IChildAProps {
onSomething: (evt)=>void
}
render() {
//Do some logic from the value in testList property
if(this.state.testList == blah blah)...
return (
<button onClick={this.props.onSomething({id:321, value:"wassup! I'm ChildA."})}>ChildA</button>
)
}
//Inside ChildB Component
export IChildBProps {
onSomethingElse: (evt)=>void
}
render() {
//Do some logic from the value in testList property
if(this.state.testList == blah blah)...
return (
<button onClick={this.props.onSomething({id:123, value:"yo! I'm ChildB."})}>ChildB</button>
)
}
At this point, I'm starting to wonder if the logic in that 2 handler methods, namely onSomethingHandler() and onSomethingElseHandler() in the Parent component, should actually be resided inside the child components themselves? I thought of this because those logic look like something the child component should be handling on their own to serve their purpose. The parent component shouldn't do it for them or it might just grow messy. But I've no choice because of how I'm handling their communication. Apart from this, I also created a new state simply just to allow them to communicate.
So far, this is still relatively manageable. But in my own experiment, it has got to a stage where I've children component nested inside another children components that need to communicate across other children components of the same (or sometimes different) level. Using states for communication also meant that I have many states all over the place, which doesn't look like a good idea to me. And the parent components ended up with tons of messy callback handler methods to manage all that propagation of data up and down the component tree.
The situation is so messy that I can at most illustrate it as something like so:
And you can see in the above illustration, ChildB ended up having yet another state just to help passing that information between its children components.
I'm sure I'm missing something that I should know about React. The callbacks I'm having in the parent components seem a little too much just to handle data propagation. How should I really organise the communication of children components in a clean and maintainable way?
Every React programmer hits this wall at some point in time. I did too. The answer is to use Redux for state management. You have experienced how tedious it is to use React's native state.
Redux is a state management mechanism which can be used in conjunction with React. So you won't be using React's state, instead you will use Redux.
Redux provides a single store, where the state of entire application is stored. You can access the state in your components using connect() method.
But there is a caveat. Not all of the react components are connected to the Redux store. There are two types of components-
Smart/connected components: Connected to redux store
Dumb components: Dependent on connected components
The idea is to pass the state from redux store to Connected components via React's props. The connected components can directly consume state from the store. The dumb components are not directly connected to the redux store. The connected components also pass the state to the dumb components via props. So you see, React's state is bypassed altogether. Now, if you want to change the state, following events must happen-
An event is fired from the smart/dumb component.
Actions are dispatched to the store
Reducers create a new state according to the actions.
A new state will be stored in the store.
Store will return new state to the connected components via connect() through props
Dumb components will receive new state from connected components through props
What are actions and reducers?
Actions are nothing but javascript objects that describe how to change the state.
Reducer is a "pure" function which builds and returns the new state tree according to the action dispatched to the store.
Redux - http://redux.js.org/
Redux-thunk - https://github.com/gaearon/redux-thunk
Redux-saga - https://github.com/yelouafi/redux-saga
Most fashion way is using Redux.js (or flux.js) to matain your child components state.
http://redux.js.org/
If you don't like invoke third party js. You can use refs property:
https://facebook.github.io/react/docs/more-about-refs.html
We can use the react context API,
Context provides a way to pass data through the component tree without having to pass props down manually at every level
Also, note that Mark Erikson has mentioned in his blog,
Yes, the new context API is going to be great for passing down data to deeply nested components - that's exactly what it was designed for.
If you're only using Redux to avoid passing down props, context could replace Redux - but then you probably didn't need Redux in the first place.
Context also doesn't give you anything like the Redux DevTools, the ability to trace your state updates, middleware to add centralized application logic, and other powerful capabilities that Redux enables.
To handle scenarios you mentioned, context API is a good option and you don't have to use additional libraries for that.

Categories