It is believed that global data synchronization is a problem that every front-end development will encounter. In the actual development process, the more common methods are Redux, MOBx, VUex and so on

However, after using react hooks, there is a simpler and more elegant way to use the useContext hook

UseContext is a natural thing to use in react projects. However, our project team recently decided to use taro to rebuild the project. We spent a lot of time on technical research, so WE decided to write a summary to help you.

For details about how to use useContext, see the official documentation

Used in taro version 2.2.6

In actual development projects, the use of useContext was not very convenient, so I used the source code of the unstuccation-Next library to create a hook of useContainer locally. CreateContext: replace the react. createContext with Taro. CreateContext, and you can use it happily

Step 1: Create usecontainer.ts

import Taro from "@tarojs/taro";

const EMPTY: unique symbol = Symbol();

exportinterface ContainerProviderProps<State = void> { initialState? : State; children: any; }export interface Container<Value, State = void> {
  Provider: any;
  useContainer: () => Value;
}

export functioncreateContainer<Value, State = void>( useHook: (initialState? : State) => Value ): Container<Value, State> {let Context = Taro.createContext<Value | typeof EMPTY>(EMPTY);

  function Provider(props: ContainerProviderProps<State>) {
    let value = useHook(props.initialState);
    return <Context.Provider value={value}>{props.children}</Context.Provider>;
  }

  function useContainer(): Value {
    let value = Taro.useContext(Context);
    if (value === EMPTY) {
      throw new Error("Component must be wrapped with <Container.Provider>");
    }
    return value;
  }

  return { Provider, useContainer };
}

export function useContainer<Value, State = void>(
  container: Container<Value, State>
): Value {
  return container.useContainer();
}
Copy the code

Step 2: Write some data that needs to be used globally

import { createContainer } from "./useContainer";
import { useState } from "@tarojs/taro";

export default createContainer(() => {
  const [count, setCount] = useState(0); // We can do some data retrieval operations, such as sending requestsreturn {
    count,
    setCount,
  };
})
Copy the code

Step 3: In the entry file app.tsx, inject global data

import Container from "./hooks/index";

# omit some code

Taro.render(
  <Container.Provider>
    <App />
  </Container.Provider>,
  document.getElementById("app"));Copy the code

The catch here is that we can’t write injection code in the App class because render doesn’t actually work.

Write the test data and run NPM run dev:h5 to display our injected global data in component and nested pages

However,…… does not appear to be supported in appplets running NPM Run Dev: Retry

Just in time for the research, Taro 3.0 was released, so we have updated Taro to see if there is any support for it

Used in taro 3.0.0-RC.6

  • throughtaro update selfCommand, we will update Taro to the latest version
  • taro init my-taro-demoInitialize a project
  • Taro 3.0 has React built in, so we can introduce it directlyunstated-nextThis package does not need to create a local useContainer
  • Repeat Step 2
  • Change app.ts in the initialization project to app.tsx(highlighted), modify app.tsx
import Container from "./hooks/container";

# omit some code

 render() {
    return <Container.Provider>{this.props.children}</Container.Provider>;
  }
Copy the code

Finally, NPM run dev: H5 and NPM run dev: repeatep can be fully evaluated