[Concent Express] (1) Define and share module state

Open source is not easy, thank you for your support, ❤ star concent^_^

Preamble

**[Concent Express]** is a series of articles to help beginners get started concentquickly, and learn and understand concent state management ideas without obstacles.

Although it is easier to understand after reading this article after learning and using state management libraries such as reduxand , but users who have not used any state management library can also get started very quickly , and the real 0 obstacle to learn to use it and connect to your in react app.mboxconcent

Note that 0 obstacles are emphasized above , including two aspects of learning to use and accessing applications. In order to achieve this purpose, the api must be simple enough. How simple is it? It is so simple that it is react100% consistent, so that novices do not need to understand additional overviews, and can access state management in the way of writing react components, but it also retains a more advanced abstract interface, so that veterans can follow reduxthe pattern to organize the code.

Come on, show it! The key APIs explained in this issue include three top-level APIs run, useConcent, , registerand an instance context API setState. If you learn to use these four APIs, you will already use Concent as your state management solution.

Hello world

All frameworks will use Hello worldas a guide, and we are no exception here to see how simple the concentversion is.Hello world

run defines the module

Like redux, concent has a single global state tree, which is an ordinary json object, but the first-level key is planned as a module name to help users divide the state into multiple modules according to business scenarios, which is convenient for separate management.

Here we need to use runthe interface to start concent and load the module configuration, configure a hellomodule named, and define the state for it

import { run } from 'concent';

run({
  hello: {
    state: { greeting: 'Hello world' },
  },
});

register register class component

After the module is defined, our component needs to consume the state of the module. For class components, you registercan use it

import { register } from 'concent';

@register('hello')
class HelloCls extends React.Component{
  state = { greeting: '' };
  changeGreeting = (e)=> this.setState({greeting: e.target.value})
  render(){
    return <input value={this.state.greeting} onChange={this.changeGreeting} />
  }
}

The appeal code uses the registerinterface to HelloClsregister the component as a hellomodule. Concent will thisinject an instance context into the current component ctxfor reading data and calling the modification method. At the same time, it also silently replaces the statesum on this, so that the setStateuser can 0 change the code of the original component. , registeryou can access state management by just decorating the class component. This is the basis for learning to use and access the react application with zero obstacles . For beginners, if you can write a react component, you will already use concentrate, without any Additional study costs.

this.state === this.ctx.state; // true
this.setState === this.ctx.setState; // true

In the above code, a class member variable is also declared stateequal to { greeting: '' }, because it greetinghas the same name as the module state, so its value will be replaced by the module before the first rendering Hello world. In fact, this class member variable can not be declared here state, write It's just to ensure that removing registerthe decorator the component will work without getting an undefinedinitial greetingvalue.

useConcent to register function components

Using the useConcentinterface to register the module to which the current component belongs useConcentwill return the instance context object ctxof the current component, which is equivalent to the above class component this.ctx, we only need to deconstruct it to take out the statesum setState.

import { useConcent } from 'concent';

function HelloFn(){
  const { state, setState } = useConcent('hello');
  const changeGreeting = (e)=> setState({greeting: e.target.value})
  return <input value={state.greeting} onChange={changeGreeting} />
}

render component

Finally, let's take a look at the complete code. We found that the top-level Providercomponent wraps the root component, because the concent does not rely on React Context apithe implementation of state management, but maintains an independent global context independently, so you connect it in the existing project. Incorporation into the concent is very easy, plug and play, without any additional modification.

Since HelloClsboth and HelloFncomponents belong to hellomodules, any instance of them modifies the state of the module, and concentrate will store it in the store and synchronize it to other helloinstances that belong to the same module. State sharing is as simple as that.

import ReactDOM from 'react-dom';
import { run } from 'concent';
import { register, useConcent } from 'concent';

run({/** 略 */});

@register('hello')
class HelloCls extends React.Component{/** 略 */}

function HelloFn(){/** 略 */}

const App = ()=>(
  <div>
     <HelloCls />
     <HelloFn />
  </div>
);

ReactDOM.render(App, document.getElementById('root'));

Click me to view the source code

Dependency collection

Whether it is a class component or a function component, the obtained stateobject has been converted into a Proxyproxy object, which is responsible for collecting the data dependencies of the current rendering. Therefore, if it is a conditional read state, it is recommended to use the delayed destructuring method, so that every rendering Lock down the smallest dependency list, reduce redundant rendering, and get better performance.

function HelloFn(){
  const { state, setState, syncBool } = useConcent({module:'hello', state:{show:true}});
  const changeGreeting = (e)=> setState({greeting: e.target.value});
  // 当show为true时,当前实例的依赖是['greeting'],其他任意地方修改了greeting值都会触发当前实例重渲染
  // 当show为false时,当前实例无依赖,其他任意地方修改了greeting值不会影响当前实例重渲染
  return (
  	<>
    {state.show?<input value={state.greeting} onChange={changeGreeting} />:'no input'}
    <button onClick={syncBool('show')}>toggle show</button>
    </>
  );
}

Consume module state across multiple modules

When a component needs to consume data from multiple modules, connectparameters can be used to declare multiple modules to connect to.

Use the connect parameter to connect multiple modules

As shown in the following example, connect the two modules bar and baz to ctx.connectedStateobtain the status of the target module:

@register({connect:['bar', 'baz']})
class extends React.Component{
  render(){
    const { bar, baz } = this.ctx.connectedState;
  }
}

connectedStateThere is still a dependency collection behavior from the obtained module state, so if there is a conditional rendering statement, the delayed destructuring method is recommended.

Use setModuleState to modify the state

ctx.setModuleStateModify the target module state by calling the instance context api

changeName = e=> this.ctx.setModuleState('bar', {name: e.target.value})

Epilogue

This article only demonstrates the most basic api usage to help you get started quickly. If you are already an old driver, especially vue3 one pieceat this juncture when the official release has been announced, if you are very disdainful of such clumsy code organization, temporarily Don't rush to deny it first, and open the official website to see other features, there must be highlights you like, including composition api tailored for react , module-level reducer, computed, watch, lifecycleand other new features. arrive.

Concent carries a complete set of solutions to support the progressive development of react components, that is, without interfering with the development philosophy and component form of react itself, and at the same time, it can obtain huge performance benefits, which means that we can develop bottom-up incremental Iteration, division of state modules, management of derived data, classification of event models, and separation of business codes can be gradually outlined and stripped out in the development process. For development, all domain models and business modules are abstracted clearly at the beginning, and at the same time, they can be adjusted very quickly and flexibly in the iterative process and affect the entire project structure.

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324146405&siteId=291194637