Skip to content

Instantly share code, notes, and snippets.

@lequanghuylc
Last active January 17, 2023 14:13
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lequanghuylc/0a471355de80198a3ed2de2618263f21 to your computer and use it in GitHub Desktop.
Save lequanghuylc/0a471355de80198a3ed2de2618263f21 to your computer and use it in GitHub Desktop.
[Using React & React Native without State management library] #article #react

It’s common these day when React & React Native developers use State management library (like Redux). I’ve been using React & React Native for a while now and found out that Pure React is actually not bad. In this article I will share my way of doing things with React & React Native purely, without State management library (represented by Redux). 

For those of you who are struggling learning Redux, because of the overwhelming of the whole React/JSX/Babel/Webpack/Native Component/Native Module/.. and have to add Redux to the list just to solve some of React problems, or because of the high learning curve of Redux, I hope you find this article helpful.

Some of React problems with State Management

Assuming you have some knowledge of React, I will jump right in the problems that most of us encoutered at the beginning of time learning React:

  • Flow pass data down, pass event up makes us to pass data & function via props and it's hard to manage when amount of props gets huge. (Comunication between component Parent - Child )
  • Another problem when passing data & function via props is the comunication of components not in same tree component.
  • Sync data between component that share common information.

Solution? Redux ? Not so fast. People often come to Redux as it's the only way. Redux solves these problems quite well, but it come with alot of things and they make it hard to learn and apply. In this article, I will share 2 ways of approach with some tools to use in each situations.

Approach 1: Global Store - Single Source of Truth

Global Store is one of Redux's fundamental principles. It can be done only using React.

1. Context

context is rarely mentioned when people talking about React. With context you can communicate between parent component and child components without passing data & function via props (and props of components in the middle). You can read more about context here. The implementation flow with context will be:

  1. Declare context in Highest Level Component (Call as Root )
  2. Create a method in Root that can get/set state.
  3. Pass method via context
  4. Declare to receive context in Child Components and we just have to use this method to get/set state in Root.
  5. All necessary information will be store in state of Root. When it changes, Root will re-render and UI will be updated.

Example Code: https://gist.github.com/lequanghuylc/2d9c0ff12c6ac64557c0acb4a0987ff1

Warming about using context: Facebook doesn't encourage us to use context, because It is an experimental API and it is likely to break in future releases of React, and if we dont use it right, it would be a mess. But let's pause for a second and look at famous libararies:

Although it's not much but context is still be used. You just have to find a way to use it right. While wrapping it inside Root and Child, you won't work directly with context (this.store instead), and if context gets removed in future releases, we can easily update 2 files Child and Root (with other solution right below) and it's done.

2. Export method setState

This solution can totally be a replacement for context, and it's more powerful because it can communicate outside of React scope, between React Applications (in case you mix React with other frontend library in your website). The implemention flow of export method setState will be:

  1. Create a class BaseComponent
  2. Declare a static variable for BaseComponent
  3. In componentWillMount, refer that static variable to a new function that can get/set state
  4. Rewrite that static variable so it can work with many instances. (instances can be managed via id)
  5. Extends all component with BaseComponent, then you can import it and directly call that static variable to get/set state (ofcouse this component has to be mounted first).

With this solution, we can manage all components from anywhere. If we want to follow Global Store Principle, just manage Root component.

Example code: https://gist.github.com/lequanghuylc/128ad8d8822d00c632a26e2737a75b81

Approach 2: Manage state in services

service simply is some kind of code running under UI (headless) to do some small task assigned to it. Using service help you separate app logic handling and app's UI.

The implementation flow with service will be:

  1. Don't handle logic in UI Component.
  2. Create service module that can run independently & headlessly. service can be use for implementing app features (like server API wrapper, sockets, local DB, native functions).
  3. any data return from service will send to component to update UI. We can use event listener for that.

One example of service is firebase. When using firebase database, we dont know about token or something like that. Because firebase doesnt return this information and we doesn't need to know. Everything unnessary will be kept internally. firebase database only provide data, the way to CRUD data and some listener to notify when data is changed.

We can totally build a service like that to communicate with Server via API. Here is some example of build a service, using class & state for React similarity.

class ServiceAPI {
	constructor() {
      this.syncData();
   	}

	state = {}; 
    // update state directlly using this.state.something = "something"

	syncData = () => {
       // sync data with local when re-open app
    }

	login = (id, pass) => {
      // call api or something
      // token will be stored in state
    }

	logout = () => {
      
    }

	onLoggedOut = ( callback ) => {
      // listener will run callback function when user logged out
    }
}

// remember to make it singleton when export (with new keyword)
export default new ServiceAPI();

You can also use directlly event listener to communicate between components. (Example: Convert Modal component Alert to function). Take a look at react-native-event-listeners & js-events-listener (forked)

Conclusion

2 Approaches in this article is mentioned theoretically. I will update example app as soon as possible, but I think it's kinda clear and easy to apply.

So what's about Redux ?

Redux is another story. As mentioned above, Redux solves the problems quite well, but it comes with alot of things: Architecture (from flux to redux), new definitions when implement (action & reducer) and the whole ecosystem to develop the Redux way. I was just simply shared some tips & tools so you can do more with Pure React. You can use it in your own way.

If you know all about Redux & its ecosystem. Well then, nothing keeping you from not using Redux. But keep in mind that we don't have to know all that to do the job. And the problems dont stay in libraries & tools, but in our way of using them.

Let's keep our minds open and think about these. :)

@CarMoreno
Copy link

Hi @lequanghuylc thanks a lot for these tips. Just today, I was thinking about another way I can manage Global store without Redux and your article has been useful for me.

Regards :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment