创建React16.6,Mobx5 和 Typescript3 初始工程

Getting started with MOBX 5 and TypeScript 3, React 16.6

原文为一篇英文文章,整篇几乎不用翻译即可看懂,这里只做简要注解,转载信息见文末。


When looking around for example applications that use Mobx 5.x combined with Mobx-react 5.xand TypeScript 3.x I did not find any useful example. Most of the examples in the awesome mobx list reference Mobx 3.x and are really outdated.


你没理解错,作者只是想找一个example,很可惜要么找不到要么是过时的,只能自己造了。


In my example I will use MOBX to display “Hello World!”. It should showcase a couple of core concepts you will be using in an mobx application.


使用mobx做一个Hello World! 示例程序,同时讲解了使用mobx的一些核心概念


tl:dr: Source Code for this example can be found here.


源代码所在地 here

Inititalizing the project


First we need to create our project. I will use following scripts to intitialize the project.


Create-react-app with TypeScript
npx create-react-app mobx-example
cd mobx-example
npm install --save typescript @types/node @types/react @types/react-dom @types/jest

npx mv 'src/App.js' 'src/App.tsx' 
npx mv 'src/App.test.js' 'src/App.test.tsx' 
npx mv 'src/index.js' 'src/index.tsx'

npm start

补充:create-react-app@2.1.1中可以直接通过以下两种方式直接创建ts工程

  1. create-react-app myApp --typescript
  2. create-react-app myApp --scripts-version=react-scripts-ts

2.1.1以下版本未经测试


Note: I am using the npm package ‘mv’ to rename the files, this ensures that the script will work cross-plattform.

We need to run start in order to let create-react-app initalize all typescript configuration files.


MOBX
npm install --save mobx mobx-react

In the tsconfig.json you need to ensure that experimental Decorators are enabled. Add following line to your tsconfig:

"experimentalDecorators": true

启用装饰器,便可以进行如下方式的开发

@observable // 使用装饰器
public name: string = 'world';

Getting Started with MOBX


In order to use a MOBX Store you need to create a couple of things:

  • A Mobx Store
  • Configure the provider
  • Use the store in a component

使用mobx之前,需要对mobx进行一些配置

The Mobx Store

Store Directory

It is advisable to keep your stores organized in a single directory like ‘src/stores’.
mkdir src/stores


推荐开发时为mobx store单独创建一个文件夹

The Example Store

From the offical documentation to create a store it would be enough to create a class as follows:


如果按照mobx的官方文档来,那么使用class来创建一个store,这样就足够了,如下:

mobxStore.ts:
import {observable, action, computed} from 'mobx';

class MobxStore {
    @observable name = "World";

    @computed 
    public get greeting():string {
        return `Hello ${this.name}`;
    }

    @action.bound
    public setName(name:string):void {
        this.name = name;
    }
}

export mobxStore = new MobxStore();

Note: Using @computed is just a demonstration how you could create a calculated value from the current state.


使用@computed只是用来示范如何创建计算属性的


When using TypeScript this is not be enough, you need to create an interface and let our Store implement it to ensure type safety in the react component.


问题来了,当在ts中使用时这样做是不够的,需要创建接口以便我们在组件中使用时确保类型安全

export interface IMobxStore { // 导出接口声明,组件中使用store时要用
    name: string;
    greeting: string;
    setName(name:string):void;
}

Additionally we will move the initialization to its own class.

Finally our mobxStore.ts looks like this:


接口配置完就变成下面这样了

import {observable, action, computed} from 'mobx';

export interface IMobxStore {
    name: string;
    greeting: string;
    setName(name:string):void;
}

export class MobxStore implements IMobxStore {
    @observable name = "World";

    @computed 
    public get greeting():string {
        return `Hello ${this.name}`;
    }

    @action.bound
    public setName(name:string):void {
        this.name = name;
    }
}

Note: The interface could also be moved into a type definition file.


接口声明可以统一放在一个单独的类型定义文件中,方便统一管理,当然不做强制要求

Store initialization

We will now create a file src/stores/index.tsIn this file we will create an object ‘stores’ that will initialize all stores that we are using in our application.


src/stores/index.ts中统一导出所有的store

index.ts:

import { MobxStore } from "./mobxStore";

export const stores = {
    mobxStore: new MobxStore()
}

Configuring the Provider


Since we are ensuring that all stores are inititalized in a single object the configuration of the Provider is very simple In the file src/index.tsx you need to import the store object and the Provider from mobx-react:

import {Provider} from 'mobx-react';
import { stores } from './stores';

Then you need to wrap the around the . By using the spread operator for stores you ensure that all stores are registered in the provider.

<Provider {...stores}>
    <App />
</Provider>

store初始化完毕,然后在根组件中通过Provider注入store

Using the Store


In order to use a store in a component you need to inject the store into the component and (most of the time) you will also want to observe the store for changes.


使用之前先通过mobx-react中提供的 inject方法注入store,如果需要在store中值发生变化的时候自动更新组件,那么也需要添加observer,其实大部分时候都是需要监听store的变化的。


The store will be accessable via the properties. Thus we need to define an interface containing an optional variable ‘mobxStore’ of the type IMobxStore. It needs to be optional due to TypeScript not knowing that the Store is provided by the inject method. If it would be mandatory TypeScript would throw an missing props error when using .


inject注入进来的store通过props的方式进行访问,在那之前,需要先定义一个包含注入进来mobxStore变量的接口,其中变量mobxStore的类型直接从mobxStore.ts中导入进来即可。

定义的接口中mobxStore变量是可选的,因为ts无法检测它被注入进来。当然这里虽然是可选的,但是实际使用的时候,它是一定存在的。这也是下文使用! 排除掉null 和 undefined的缘故。


This in turn causes TypeScript to complain that const {greeting} = this.props.mobxStore; is not allowed, as this.props.mobxStore could be ‘undefined’. By adding the Non-null assertion operator ‘!’ you can signal the TypeScript compiler to ignore this warning.


上面就!符号做了说明

App.tsx:

import React, { Component } from 'react';
import './App.css';
import { observer, inject } from 'mobx-react';
import { IMobxStore } from './stores/mobxStore';

interface AppProps {
  mobxStore?: IMobxStore
}

@inject('mobxStore')
@observer
class App extends Component<AppProps> {
  render() {
    const {greeting} = this.props.mobxStore!;
    
    return (
      <div className="App">
        <header className="App-header">
            {greeting}
          <button onClick={this.clickHandler}>Change Greeting</button>
        </header>
        
      </div>
    );
  }

  private clickHandler = () =>{
    const {setName} = this.props.mobxStore!;
    setName("Bob");
  }
}

export default App;

Conclusion


Now if you run the application you should now see a wonderful “Hello World!” greeting and by clicking on the button it changes to “Hello Bob!” using mobx and typescript.

I hope this makes it a little simpler to get started with React, Mobx and TypeScript.

If you are interested in the project files you can get them from GitHub https://github.com/borgfriend/typescript-react-mobx-example


程序运行成功,完结!

转载声明
Published by HappyNeal
https://www.nealbuerger.com/2018/11/11/getting-started-with-mobx-5-and-typescript-3-react-16-6/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值