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

The preface

Concent is a series of articles designed to help beginners learn and understand Concent’s state management ideas.

While learning and using state management libraries such as Redux and Mbox will make this article easier to understand, anyone who has never used any state management libraries can get up to speed on Concent, a real barrier to learning how to use it and plug it into your React app.

Note that the 0 barriers highlighted above include both learning to use and accessing the application. In order to achieve this, the API must be simple enough. How simple? The React component is written in the same way that newcomers can access state management without having to understand additional overviews, but the React component also retains a higher-level abstraction interface that allows veterans to organize code in a redux fashion.

Come on, show! The key APIS in this tutorial include three top-level apirun, useConcent, register, and an instance context apisetState. Learn to use these four apis and you will already be using Concent as your state management solution.

Hello world

All frameworks start with Hello World, and we’re no exception here. See how simple the Concent version of Hello World is.

Run defines the module

Concent, like Redux, has a global single state tree, which is a common JSON object. However, the key at the first layer is planned as a module name to help users split the state into multiple modules based on business scenarios for easy management.

Here we need to start Concent using the Run interface and load the module configuration, configure a module called Hello, and define its state

import { run } from 'concent';

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

Register Registers class components

Once the module is defined, our component needs to consume the module’s state. For class components, use Register

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} />}}Copy the code

Concent will inject an instance context CTX to the current component this, which will read data and call modification methods. Concent will also silently replace state and setState on this. This is the foundation for learning how to use and connect to the React application. For starters, if you can write the React component, you already know how to use Concent without any additional learning costs.

this.state === this.ctx.state; // true
this.setState === this.ctx.setState; // true
Copy the code

In the above code, we also declare a class member variable state equal to {greeting: }, because the new greeting is the same name as the module state, the value will be replaced by the module Hello World before the first rendering. In fact, the class member variable state can be left undeclared, just to make sure that deleting the register decorator works. Instead of getting an initial greeting value of undefined.

UseConcent Registers function components

Use the useConcent interface to register the module that the current component belongs to. UseConcent will return the instance context object CTX of the current component, which is equivalent to this. CTX of the above class component.

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} />
}
Copy the code

Rendering component

When we look at the complete code, we see that the top, providerless component is wrapped around the root component, because Concent does not rely on the React Context API for state management. Instead, concent maintains a separate global Context. So it’s very easy to plug and play concent into your existing projects without any additional modifications.

Since both HelloCls and HelloFn components belong to the Hello module, when one of them changes the module state, Concent stores it to the Store and synchronizes it to other instances of the hello 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'));
Copy the code

Click me to view the source code

Depend on the collection

Both type of component and function component, to get the state object has been converted into a Proxy agent object, collect data dependent on the current rendering, so if there is a conditional state of reading, delay of deconstruction is recommended for the wording, so that the smallest dependence on every rendering lock list, reduce redundant rendering, for better performance.

function HelloFn(){
  const { state, setState, syncBool } = useConcent({module:'hello'.state: {show:true}});
  const changeGreeting = (e) = > setState({greeting: e.target.value});
  // When show is true, the current instance relies on ['greeting'], and any changes to the value elsewhere trigger the current instance to rerender
  // When show is false, the current instance has no dependencies, and changes to the new greeting value anywhere else do not affect the current instance rerender
  return (
  	<>
    {state.show?<input value={state.greeting} onChange={changeGreeting} />:'no input'}
    <button onClick={syncBool('show')} >toggle show</button>
    </>
  );
}
Copy the code

Consuming module state across multiple modules

When a component needs to consume data from multiple modules, the CONNECT parameter can be used to declare multiple modules to be connected.

Connect multiple modules using the connect parameter

As shown in the following example, connect the bar and baz modules and obtain the target module status via ctx.connectedState:

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

The module state retrieved from connectedState still has dependency collection behavior, so deferred deconstruction is recommended if conditional rendering statements are present

Use setModuleState to change the state

Modify the target module state by calling the instance context apictx.setModuleState

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

conclusion

This article just shows you the basics of the API to get you started on Concent. If you’re an old driver, especially now that Vue3 One Piece has been announced, and you don’t like the way the code is organized, don’t be too quick to dismiss it. Check out the other features on the website. There will be some highlights you’ll like, including the composition API tailored for React, new module-level features like Reducer, computed, Watch, Lifecycle, and more, all of which will be covered in a crash course.

Concent to carry a set of complete solutions, support the development of progressive react components, namely do not interfere with the react and component form itself to the development of philosophy, but also can get huge performance gains, which means that we can to the incremental iteration, the top state of module partition, derived data management, the classification of the event model, Business code space can be gradually in the development process of the outline and spun off, its process is smooth, silky, also allows us to top-down plan as a whole, the development of a start all the domain model and business module abstract clearly, at the same time in the iteration process can also be very fast flexible adjustment and affects the whole architecture of the project.