(Don’t forget to like it and follow it q-Q! Click a star on Github!!

Rako is a declarative, predictable, extensible, cohesive, simple and powerful JavaScript state container.

Unlike Redux, your project always needs RaKO!

Rako decouples your business logic from your view very well, and because Rako encourages modularity, you can even write your view logic to RaKO! Control the granularity of state and your project will be more maintainable than ever before!

Making: github.com/rabbitooops…

You can read the following article with examples: codesandbox. IO/s / 011136 QPK…

Rako’s design comes from the simplest OOP programming, simple but expressive.

const profile = {
  name: 'Tom'.gender: 'male',
  updateName(name) {
    this.name = name
  },
  updateGender(gender) {
    this.gender = gender
  }
}
profile.updateName('Jerry')
Copy the code

I believe that everyone can understand the above code, it is very simple! But the current features are too weak, let’s transform it to make it stronger, here are the features we want:

  1. Data is immutable.
  2. Each update causes some subscribe side effect.
function profile(update) {
  return {
    name: 'Tom'.gender: 'male',
    updateName(name) {
      update({name})
    },
    updateGender(gender) {
      update({gender})
    }
  }
}
const profileStore = new Store(profile)
Copy the code

It is very similar to defining a profile directly, except that the profile is wrapped in a function and updates are made using the passed parameter Update, but such a simple design can burst into great energy when combined with Rako.

Profilestore.getstate () returns {name: ‘Tom’, gender: ‘male’} when you want state, and the state is handled by object.freeze to make the data immutable.

This is very different from redux using reducer to define data. Reducer is essentially a mix of data definitions and updates, and a new state is returned each time the reducer is created! This design is problematic because it leaves the construction of state to the user rather than redux managing it for the user!!

It should be pointed out that the pure function created by reducer last day exists to adapt to the purpose of reducer. Each action returns a state, which results in that reducer must be a pure function.

Pure functions exist to fit the reducer design rather than as a benefit of a REdux!

So you’ll find that, in the real world, you always have a thing to dock with pure functions! Troublesome!

Now we subscribe to a side effect:

profileStore.subscribe(state= > console.log('subscribe', state))
Copy the code

Thus, each update will print state.

Let’s try triggering the update. Before triggering the update, we need to get the updater of profileStore:

const updater = profileStore.getUpdater()
Copy the code

Now update the name:

updater.updateName('Jerry')
Copy the code

When called, not only is the name updated, but a side effect is triggered, printing “SUBSCRIBE {name: ‘Jerry’, gender: ‘male’}”.

This is the core function of Rako.

Encourage the creation of multiple stores

Rako always encourages you to tiled your states, so provide a tool called createStores to create multiple state container stores.

const {profile$, contact$, theme$} = createStores({profile, contact, theme})
Copy the code

CreateStores returns an object, the object’s key compared to object key will add a $suffix as profileStore contactStore, themeStore shorthand.

CreateStores passes objects instead of arrays for extensibility. For extensibility, refer to redux middleware, but different from Redux, which I call enhancer, and I’m not going to go into the complexities in this introductory article. Besides, developing enhancer is not a user concern! You don’t need to know anything about developing enhancer!

High cohesion

Now let’s talk about high cohesion. You can do any initialization and asynchronous operation in the code,

function profile(update) {
  // Network request fetchProfile, if the network error, I will provide a very good plug-in to support error handling!
  fetchProfile().then(({name, gender}) = > update({name, gender}))

  // But you cannot synchronize the update
  // update({name: 'Jerry'}) wrong!

  return {
    name: null.gender: null,
    updateName(name) {
      // Network request setName
      setName(name).then((a)= > update({name}))
    },
    updateGender(gender) {
    // Network request setGender
    setGender(gender).then((a)= > update({gender}))
    }
  }
}
Copy the code

Rako didn’t have to write any boilerplate code, as Redux wrote a simple logic that was long and stinky! You can always have all your business logic in one place!

If you really understand Redux, you’ll see that dispatch, action.type, and action.payload correspond to a set of concepts:

redux concepts
dispatch Call a function
action.type The function name
action.payload Parameters of a function
dispatch({type: 'SET_NAME'.payload: 'Jerry'})
Copy the code

Exactly equivalent to

setName('Jerry')
Copy the code

To put it bluntly, redux complicates a function call!

Not only that, but because action.type is a string, an update will be triggered whether or not action.type is correct, which is an unreliable function call. And make sure that every dispatch you make executes the correct string action.type.

Rako is not designed that way. If you want to update, you can just call updateName, you can’t call an update that doesn’t exist. In short, Redux provides manual maintenance, rako provides language maintenance.

Used in React

All right! How to use Rako in React! I made Rako-React so simple that there are only two apis, and most of the time it’s easy to inject a Store into component with just one API!

Enable the decorator:

import {assign, prop} from 'rako-react'

@assign(
  prop(profile$, state => state),
  contact$
)
class App extends React.Component {}
Copy the code

Decorator not enabled:

export default assign(
  prop(profile$, state => state),
  contact$
)(App)
Copy the code

The first argument to prop is store and the second argument to mapper. Mapper is a function that passes the state and updater of a store to it and returns a new object.

(state, updater) => Object.assign({}, state, updater)
Copy the code

Assign accepts any prop or Store or even object, and it spreads out multiple states and passes them to the App. In function Component, you never need prop. You can write:

function App({name, gender, phone}) {
  // TODO
}
App = assign(profile$, contact$)(App)
Copy the code

In the future, Rako will support useProp when React 16.7 launches hook!

const {name, gender, updateName, updateGender} = useProp(profile$)
Copy the code

If you think Rako is good enough, please click “like” and click “Star” on Github for more people to see it and for you to have a chance to use Rako in your future projects!!

Github.com/rabbitooops…

Github.com/rabbitooops…

Welcome more creative ideas!