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

The preface

Nextjs is a very popular React server render application framework. It is lightweight, easy to use and has an active community. Therefore, when writing an application that requires SSR (Server side render) using React, nextJS will be the first choice. Concent is a new generation of React state management solution. It has a built-in dependency collection system and features zero-intrusion, predictability, progressive, and high performance. It also provides flexible apis such as Lifecyle and Composition API and is super simple to write. Make it easy to navigate the Massive React app.

Hello next

Here we’ll use the create-next-app command to install a basic Next sample application

npx create-next-app hello-next
Copy the code

After the execution, you can see the following directory structure

| ____public | ____pages | | ____ _app. Js/application/next to the default root component | | ____index. Js / / the default home page | | ____api / / API routing file | | | ____hello. JsCopy the code

We then execute in the project root directorynpm run devYou will see a bynextdrivenssrThe default home page

Hello concent

Here we’ll use the create-react-app command to install a basic sample concent application

npx create-react-app hello-concent --template concent-ts
Copy the code

After the execution, you can see the following directory structure

. | ____index. TSX | ____App TSX | ____types / / store the type definition | ____features / / functional components list | | ____counter / / counter function | | . | ____Counter TSX composite components / / counter | | | ____model/model/counter (contain state, reducer, computed) | ____models / / other global universal model definition |____configsCopy the code

Go to the project directory and executenpm iAnd then executenpm startYou see a default counter page

You can also read and edit it online by clicking here.

Of course, it’s super easy to integrate concent into existing projects because it doesn’t require a top-level Provider, just a pre-configured model.

import { run } from 'concent';

run({ // Define a counter model
  counter: {
    state: { num: 1.bigNum: 10 },
    reducer: {
      add(payload, moduleState) {
        return { num: moduleState + 1 };
      },
      async asyncAddBig() {
        await new Promise(resolve= > setTimeout(resolve, 1000));
        return { bigNum: moduleState + 10}; }},computed: {
      doubleNum: ({ num }) = > num * 2.// This function is triggered only when num changes}}})Copy the code

After global can plug and play, component and function component can be used to read the data in the same way or call a method, on the key, if the UI is conditional statements control whether to consume or derived data, recommend the delay deconstruction method and this can allow concent in after each round of rendering the view of data collection, the minimum size dependence

// ###### function component
function Demo(){
  // For example, state and moduleComputed are read on demand. Deferred deconstruction is recommended
  const { state: { num, numBig }, moduleComputed: { doubleNum }, mr } = useConcent('counter'); 
  / /... UI logic, binding data, binding methods
}

// ###### class component
const DemoCls = register('counter') (class DemoCls extends React.Component{
   render(){
      const { state: { num, numBig }, moduleComputed: { doubleNum }, mr } = this.ctx; 
      / /... UI logic, binding data, binding methods}})Copy the code

Introduce Concent in Next

Next’s base sample directory contains the _app.js file that is the root component of the Next application

import '.. /styles/globals.css'

function MyApp({ Component, pageProps }) {
  return <Component {. pageProps} / >
}

export default MyApp
Copy the code

Since the model must be configured in advance to use Concent, we just need to create a runconcent.js file

import { run } from 'concent'
import * as models from './models';

run(models);
Copy the code

You can then import it in the _app.js file, so that all the children of the root component can get the store data and transfer the store method correctly.

import '.. /styles/globals.css'+ import './runConcent'function MyApp({ Component, pageProps }) { return <Component {... pageProps} /> } export default MyAppCopy the code

Next we create a counter. Js file in the Pages directory of next, representing a page component, so that the browser can call in the /counter route to ask for the render view of the component.

import React from 'react'
import { useConcent } from 'concent'
import router from 'next/router'

// use next/router to do browser side router jump
function toHomePage(){
  router.push('/');
}

export default function Counter() {
  const { state, mr, moduleComputed } = useConcent('home')

  return (
    <div>
      this is counter page
      <h1>num: {state.num}</h1>
      <h1>doubleNum: {moduleComputed.doubleNum}</h1>
      <button onClick={mr.add}>add</button>
      <button onClick={toHomePage}>to home page</button>
    </div>
  );
}
Copy the code

And there you have it, a Next app with Concent. Isn’t that easy? ^_^

Support for pre-rendering

Next provides two levels of pre-rendering interfaces, namely getServerSideProps and getStaticProps. The difference between the two interfaces is that the execution time of getServerSideProps is different. GetServerSideProps is executed at each request page, while getStaticProps is executed at build time. Let’s take a look at getServerSideProps and see how we can use Concent for pre-rendering support.

First of all, we don’t care about Concent, do pre-render support in Next, just expose a getServerSideProps interface in your page component.

// This function is called every time a page change is requested
export async function getServerSideProps() {
  // Call the external API to get the list of blog posts
  const res = await fetch('https://... /posts')
  const posts = await res.json()

  // By returning the {props: posts} object, the PostPage component will receive the 'posts' argument when rendering
  return {
    props: { posts },
  }
}

function PostPage({ posts }) { // The posts parameter is received here
  // Render posts...
}

export default PostPage
Copy the code

In addition to exposing the getServerSideProps interface, we can look at the _app.js root component file and see what the key point is!

function MyApp({ Component, pageProps }) {
  return <Component {. pageProps} / >
}
export default MyApp
Copy the code

The pageProps in the parameter list is the object that getServerSideProps is pointing to in the return result, and next passes it transparently to the target page component, so we can deconstruct posts in the PostPage parameter list.

{module:string, state: object} and store the return result of getStaticProps in _app.js

// This function is called on each request
export async function getServerSideProps() {
  // Call the external API to get the list of blog posts
  await delay();
  const posts = [
    { id: 1.name: 'post1 -----' },
    { id: 2.name: 'post2 --- welcome to use concent'},];// This return object is passed transparently to the pageProps of the root component, where it returns the module and the state entity object to which the state belongs
  // Record the state to store there
  return {
    props: {
      module: 'test'.state: { posts },
    }
  };
}
Copy the code

The root component file changes as follows

import '.. /styles/globals.css';+ import './runConcent';
+ import { setState } from 'concent';Function MyApp({Component, pageProps}) {// This logs the return status of getServerSideProps to the corresponding module in the store+ if (pageProps.module) {
+ setState(pageProps.module, pageProps.state);
+}return <Component {... pageProps} /> } export default MyApp;Copy the code

Then we implement the post-page code for the page component as follows

const PostList = React.memo(function () {
  const { state } = useConcent('test');
  return (
    <div>
      {state.posts.map(item => <h3 key={item.id}>{item.name}</h3>)}
    </div>
  );
});

const PostLength = React.memo(function () {
  const { state } = useConcent('test');
  return <h1>{state.posts.length}</h1>;
});

export default function PostPage() {
  return (
    <div>
      <h1>this is post page</h1>
      <PostList />
      <PostLength />
      <button onClick={toHomePage}>to home page</button>
    </div>
  );
}
Copy the code

Then we open the browser/post-pagePage, click to view the source code will see this is a server-side pre-rendered page

In the same way, we can replace getServerSideProps with getStaticProps, and the whole process will still work. Take a look at the clone code to see for yourself.

git clone https://github.com/concentjs/ssr-demo-1
Copy the code

The appendix

doc

  • next-js doc
  • concent doc

CloudBase CMS

Welcome to CloudBase CMS to create a one-stop cloud content management system. It is a Headless content management platform based on Node.js launched by cloud development, which provides rich content management functions. It is easy to install, easy to develop again, and closely integrated with the cloud development ecosystem. Help developers improve development efficiency.

Concent already has strong support for its admin backend, and the new admin interface is much more beautiful and thoughtful.

FFCreator

Welcome to FFCreator, which is a lightweight and flexible short video processing library based on Node.js. All you need to do is add a few pictures or video clips and a piece of background music to quickly create a cool video clip.

FFCreator is a lightweight and simple solution that requires few dependencies and a low machine configuration to start working quickly. And it simulates 90 percent of animate. CSS animation, you can easily turn web page side animation into video, really cool.