Usage of mutable objects inside React Native + Redux app - javascript

I'm new to React (and React Native in particular), and I'm trying to come up with the right application design.
I have a separate JavaScript module, unrelated to React; the module contains some objects with methods, some of them mutate objects, some have side effects (like, subscribe/unsubscribe to/from the server events, or add/remove listeners to local object's events), etc.
I'd like to reuse this JavaScript module inside my React Native app, but it seems that it won't play well together. In Redux (and some other state managers as well), state needs to be represented as a plain immutable JS object, and instead of mutating existing objects, we create new objects instead. So I can't use my existing JS objects as a state directly.
I probably could use some wrappers around my existing JS code (mutating, and full of side effects), but it doesn't seem a nice solution: a lot of repetition, and the end result is unlikely to be elegant.
On the other hand, I'm not quite happy reimplementing the whole thing to fit into React's world, to make it idiomatic.
And on the one more other hand, I could just forget about Redux, and use plain state of React's components, but I feel it'll be a mess.
I'd like to get some suggestions from experiensed React + Redux people. What would you recommend?

It's hard to say exactly without seeing what the mystery module does or exposes. But consider converting the module into one or more reducers and then use Redux's combineReducers to target pieces of the overall store that will be contained exclusively in your module.
Then you will need to add reducer methods that always return new objects as required by Redux, but you won't need to modify every function in the existing code.
This article by Dan Abramov helped me understand reducer composition.
See also Handling Actions in the docs for help on how to write good reducer methods that only modify a small piece of the store.

Related

When should I use Vuex?

Now I start to learn vue, and I'm creating SPA for editing database. Now I can't understand where I should use a Vuex. I can use props and $emit everywhere and it can help me find needed parameter. So for what case I should use Vuex?
According to this awesome tip from Vuedose blog
Vue.js 2.6 introduced some new features, and one I really like is the new global observable API.
Now you can create reactive objects outside the Vue.js components scope. And, when you use them in the components, it will trigger render updates appropriately.
In that way, you can create very simple stores without the need of Vuex, perfect for simple scenarios like those cases where you need to share some external state across components.
For this tip example, you’re going to build a simple count functionality where you externalise the state to our own store.
First create store.js:
import Vue from "vue";
export const store = Vue.observable({
count: 0
});
If you feel comfortable with the idea of mutations and actions, you can use that pattern just by creating plain functions to update the data:
import Vue from "vue";
export const store = Vue.observable({
count: 0
});
export const mutations = {
setCount(count) {
store.count = count;
}
};
Now you just need to use it in a component. To access the state, just like in Vuex, we’ll use computed properties, and methods for the mutations:
<template>
<div>
<p>Count: {{ count }}</p>
<button #click="setCount(count + 1);">+ 1</button>
<button #click="setCount(count - 1);">- 1</button>
</div>
</template>
<script>
import { store, mutations } from "./store";
export default {
computed: {
count() {
return store.count;
}
},
methods: {
setCount: mutations.setCount
}
};
</script>
Update: Since this answer was written, things changed. If you're considering using Vuex today, don't. Use Pinia instead. Here's a decent answer outlining why you should favor Pinia over Vuex. However, what I said about the Redux pattern below, still stands.
The main purpose of using Vuex (which is Vue's version of Redux) is state (or data) management. In layman's terms, it's having a single source of truth (for your data).
It opposes the common pattern of emitting an event when data changed so other parts of the application can keep their data in sync with the current component's data.
Rather than allowing one particular component to change the data directly, you delegate the change to a separate module: the store. Any component using that data will be notified about the change. This becomes extremely useful in complex applications, where the common emit pattern runs the risk of creating cyclic update loops.
Apps using the Redux pattern benefit from:
predictability of outcome,
ease of testing
code maintainability and scalability
separation of concerns
ease of debugging (time travel: the ability to undo or replay a particular change for debugging purposes).
In short, it gives developers control and confidence, as it makes understanding and modifying complex code, data or app behavior significantly easier.
Like any other pattern (or system, or tool), the Redux pattern can be over-used. It should be obvious you don't have to keep data that's only used by one component in the store. Since no other component needs to know about any changes to that data, one should manage it in the component using it.
Vuex allows organisation of data into modules so you can keep everything tidy and maintainable.
Last, but not least, one of the most useful benefits of using the Redux pattern is making SSR (server side rendering) implementation a breeze. SSR greatly improves optimization and user experience and increases the perceived performance of the application.
Yes, you can do anything without the use of Vuex, but with time, if your application is getting larger then it would be difficult to maintain,
according to vuex documentation,
problem one, passing props can be tedious for deeply nested
components, and simply doesn't work for sibling components. problem
two, we often find ourselves resorting to solutions such as reaching
for direct parent/child instance references or trying to mutate and
synchronize multiple copies of the state via events. Both of these
patterns are brittle and quickly lead to unmaintainable code.
Hope it answers your question.
Look at the vuex documentation; it describes all the reasons why/when you want to use vuex https://vuex.vuejs.org.
For instance, multiple components require the same information, controlling mutations, validations, etc.

Returning plain JS object from memoized selector using Immutable.js

I'm working on a React + redux + Immutable.js + reselect application. I'm considering a design where I'm using Immutable.js in the reducers and sagas, but don't want to couple this library with the smart components, so my presentational part of the app as clean as possible.
According to redux documentation your selectors should always return Immutable object.
My idea is to compute derived state in reselect selector and return plain JS object. If I use memoized selector, new object won't be created on every call if underlaying part of redux state is the same, so my component won't be rerendered unless needed.
I know that I'll partially pay with composability, since the selector cannot be uses as an input for other Immutable.js-ready selectors, but I'll get much cleaner smart components.
Are the any other drawbacks of such solution?
Why does redux documentation so strongly encourages to push Immutable object to smart components?
Are the any other drawbacks of such solution?
toJS is an expensive operation, even if memoized. The argument is why toJS if you don't have to?
Why does redux documentation so strongly encourages to push Immutable object to smart components?
The aforementioned, plus it makes reasoning about the whole redux pipeline easier, i.e. any mutations (side effects/morphisms) to state are easier to wrap one's head around as there's a clear flow and point where changes occur.
With all that said, it comes down to preference and where one feels the bottlenecks/trade-offs in one's architecture are. If you feel having a clean separation outweighs the potential risks/caveats with having toJS in the selector, then that's the correct call for your architecture.
On a side note regarding loss of composability in the selector, you could always have two selectors, one that returns the immutable state--used for selector composition, and one that uses the immutable state selector and calls toJS, where appropriate.
Are the any other drawbacks of such solution?
toJS is expensive and also debugging the application becomes more complex.
Why does redux documentation so strongly encourages to push Immutable object to smart components?
Immutable objects are validated more deeper than plain Objects. In case of oldObject === newObject validation plain objects will be compared on a global level whereas oldImmutableObject === newImmutableObject is compared more deeper. This is more efficient on the render tree avoiding unnecessary updates on rendering React components.
Easy to modify objects with helper functions. get, set and more.
Unnecessary data copying is avoided.

Why is the concept of immutability is embraced in React and its ecosystem?

in ES6, there are additional ways to declare a variable such as let and const
A variable declared with const cannot be re-assigned or re-declared.
Why are there so many const declarations in React application and what are the distinctive benefits from using const over var and let?
First answer by #Carcigenicate explains the usage of const correctly.
But const keyword alone is not sufficient to achieve immutability.
e.g. You can mutate a const array :
const a = [12,14,15];
a[0] = 13; // allowed. but mutate a value.
To achieve immutability to object at property level, new JS provide using Object.freeze(), .assign() etc or you can also utilize new library like immutableJS (there are few more good one to check out).
About Immutability in React, React components are pure functions. They accept props and return view.
Pure functions are foundation of Functional Programming. They lead to all sort of benefits (enable composition, simple to comprehend the unit of code which is function, easy to test and many more). Pure function does not have any side effect. It must not modify argument object also, and treat it as immutable.
DOM created by React components forms virtual DOM, and detects the data change called via setState only. On call of setState, it reacts and trigger its real DOM update algorithm. If a developer updates props, this won't happen. This post explain this: http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html
React encourages one way data flow, Updated State flow down from top to bottom as props, and reaction to user action flow up as method call. One way data flow make it easy to debug/understand the react apps.
I created following diagram to understand the example illustrated in official React docs
It's pretty common to have multiple parts of code relying on the same variable (PI for example) . If that variable is a constant, and immutable, you dont need to worry about it changing at unpredictable times based on who may potentially be writing to it.
If a variable shouldn't change, it should be made a constant to ensure that it it isn't reassigned accidentally. That way you can trust that the value of the variable will always be the same.
Note, const has very little to do with immutability. Even if you have a constant reference to an object, the object itself can still change.

Should I nest immutable.js Map and List in redux application?

I am using immutable.js in a redux application and I am wondering whether I should always use immutable.js datastructures where I would have used JSON object or array in a normal application.
Otherwise said, should the store of a redux application be a pure immutable.js datastructure or it's okay to mix with plain old javascript objects and arrays?
It's totally okay to use "old" javascript objects or array. If you use immutable.js everywhere, you will get more advantages than using "old" js objects. From their website, immutable.js is leading to much simpler application development, no defensive copying, and enabling advanced memoization and change detection techniques with simple logic.. It will enforce the use of functional programming patterns like pure function, which redux use a lot. You will avoid useless object mutation and related bugs. Your code will be more along the lines of the redux way of thinking. It might take more time to code with immutable.js, but your code will be better, faster and easier to update overall. Since you're using react. You won't get a lot of benefits using immutable.js inside a component because react has a great way to handle object change easily. I will suggest you to try to keep your redux store as pure immutable.js data structure as possible to avoid strange side effects and bugs. You will become used to it, but like I said before, it's totally fine to use non immutable-js data structure. Sometimes it will be easier not to use it. I will suggest you to try using it everywhere and you will be able to see by yourself if it's a waste of time or not.

ReactJS local vs global state and implementing redux at a later time

So we are about two months in on a project. This is the first time I have ever managed code writers and not written the code myself. I've been reading their code for the last week. What was suppose to be a simple React app has turned into a spaghetti mess.
I understand: redux helps to manage global state. But should that mean that all buttons should map to a global "action?" This has seemed to create this entire mess of objects scattered throughout the entire app. I keep asking myself, why are we using global state for everything when local state could be used for 90% of the application. This is the kind of code that gives me heartburn:
let subitems = SidebarItems[state.type].sub_items;
Store.dispatch(SidebarSubItemHandler(item.action, subitems[0], null));
if(item.sub_items[subitems[0]].param) {
browserHistory.push(`${item.sub_items[subitems[0]].path}/${item.sub_items[subitems[0]].param}`);
} else {
browserHistory.push(item.sub_items[subitems[0]].path);
}
subItembuttons = Object.keys(this.props.subitems.sub_items).map(subitem => {
let subItem = this.props.subitems.sub_items[subitem];
return <li className={this.props.activeSubItem.action == subItem.action ? "bottom-bar-item active" : "bottom-bar-item"}
onClick={e => this.props.onClickSubItem(e, subItem)}
key={subItem.action} style={this.props.subitems.inlineStyles.mobileSubItemLI}>
{subItem.item}
</li>;
});
The application is littered with all kinds of objects like these that map to "action" objects. So at this point we are making the decision to scrap the entire project and restart from scratch, but without redux. Let's try to do as much as possible using local state only. When it comes time, and we need global state for something, ONLY implement it for that something, not every single action in the app. Does this make sense?
So I guess my question is: If we develop an app using local state and just fundamental React, will we be creating un-reversable problems that would prevent us from implementing redux on a per item basis?
Quoting from the relevant Redux FAQ entry at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state:
Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it.
Some common rules of thumb for determing what kind of data should be put into Redux:
Do other parts of the application care about this data?
Do you need to be able to create further derived data based on this original data?
Is the same data being used to drive multiple components?
Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
Per your specific question: if you use the "container component" pattern fairly consistently, it should be relatively straightforward to swap those "plain React" containers for Redux-connected containers down the line. See https://github.com/markerikson/react-redux-links/blob/master/react-component-patterns.md#component-categories for articles on the "container/presentational component" pattern.
Two other thoughts. First, I recently co-authored an article that discusses why you might want to use Redux in a React application.
Second: yeah, that code looks kinda ugly. I'm hoping those are at least three different snippets from different parts of the codebase, rather than one snippet, but that's rather hard to read. The repeated use of "sub_items" and "subitems" seems like a bit of a red flag, readability-wise.
It also doesn't look like it's following good Redux practices. For example, idiomatic Redux code almost never references the store directly. Instead, references to dispatch and getState are available via middleware, and thus can be used in action creators via redux-thunk and redux-saga. Connected components can also access dispatch.
Overall: you are absolutely welcome to use as much or as little Redux as you want, and as much or as little local component state as you want. I think the larger issue, though, is how well your team actually understands Redux, and how they're trying to use it.

Categories

Resources