极速开发 React — Reason 2

作者: zidea | 来源:发表于2019-03-15 07:41 被阅读63次
Speed_Racer_promotional_image.jpg

现在是速度至上的时代,我们必须以一敌百。才能立于不败之地。

FCJG300-0043.jpg
面对越来越复杂的业务逻辑,我们只能全速向前冲,这一切都需要有技术作为保障。所以我们需要选择一个能够实现快速开发的技术。
th.jpg
reason react 网址
个人选择并且推荐使用 reason 来开发
极速开发 React — Reason 1
  • 更安全,更简洁的方式去构建 React 组件
  • 完全兼容 JSX
  • 类型安全兼容 javascript 编写的组件
  • 用于一种全新的表述型 API 来描述状态管理
rr_001.JPG

搭建项目

npm install -g bs-platform
bsb -init my-react-app -theme react
cd my-react-app && npm install && npm start
npm run webpack

创建 index.html

我们将架构默认的工程文件都删除,自己来写一个列表的 demo。先创建一个 index.html。

  • 引入 Index.js 最终 webpack 打包后会引用 index.js
  • id 为 app 的 div,我们的应用都写在这个 div 下面
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Zidea ReasonReact Examples</title>
</head>
<body>
  <div id="app"></div>
  <script src="Index.js"></script>
</body>
</html>

然后创建 re 结尾的 reason 文件

ReactDOMRe.renderToElementWithId(<TutListComponent />, "app");

我们这里可能需要使用 bs-json 和 bs-fetch,我们可以用 npm 来安装一下这两个库,或者说是 reason 的模块。然后需要 bsconfig 文件添加依赖,这样我们就可以在工程中使用这两模块。

 "bs-dependencies": [
    "reason-react",
    "@glennsl/bs-json",
    "bs-fetch"
  ],

我这里用 python flask 写了一个服务,返回值为


rr_002.JPG
  • 我们先定义一个数据结构,用 type 定义 tut 类型 string
    我们可以定义 type 定义的数据类型,reason 是一种类型的语言,这对没有类型的 javascript 是一个强大的支持。
type tut = {title:string, body:string}

我们这里根据官网的 demo 就先简单地定义为 string

type tut = string;
  • reason react 给我们提供两种创建组件模板
  1. statelessComponent
  2. reducerComponent
    这里我们创建 reducerComponent 类型组件
  • 创建 state 状态 这也是 ocaml 的语法,应该算是类型匹配吧,有了这个就可以保证我们在做分支语句不会漏掉某些可能性。action 定义方式也是一样,有关 action 和 state 如果大家还没有接触过可以看一看 redux,以后我会分享的。
type state = 
    | Loading
    | Loaded(array(tut))
    | Error;
  • 定义模块 Decode
    我们可以在模块定中定义类型和方法,这里我们定义了一个 tuts 的方法,用于解析服务端返回的数据,然后我们使用 Json 模块的 Decode 方法,这个 Json 模块需要我们手动引用一下。|> 如果用过 linux 的脚本或者写过 powershell 的程序员可能不会陌生,这是链式操作。我们接受返回 json -> 然后获取 messages 字段的值类型为 string 的数组 -> 然后对数组进行映射。
module Decode = {
    let tuts = json: array(string) =>
        Json.Decode.(
            json |> field("messages",array(string)) |> Array.map(_, tut => tut)
        )
}


- **make**
是让我们在编译时生产 component 的方法。

  • 初始化我们 state
 initialState: _state => Loading,

然后就是 reducer 这纯函数,最近然后 mvi 模式,再次开始研究 reducer,reduce 我还是在学习 redux + react + rxjs 时学习过,为了理解也花费不少精力。这里简单介绍一下,毕竟 reduce 不是我们今天的重点。reduce 是一个纯函数,接受 action(动作)返回一个新的 state。然后我们 reducer 中根据 action 进行分支更新我们状态。这里我发现没有用引入 redux 却做了 redux 事情,代码表意也挺好,给 reason 一个赞。

  • 在说一下 Promise ,对于了解 es6 前端 promise 应该不是很陌生,这里同样使用管道符来进行处理。
Js.Promise.(
                            Fetch.fetch("http://localhost:4600/get_tuts")
                            |> then_(Fetch.Response.json)
                            |> then_(json =>
                                json
                                |> Decode.tuts
                                |> (tuts => self.send(TutsFetched(tuts)))
                                |> resolve
                            )
                            |> catch(_err => 
                                    Js.Promise.resolve(self.send(TutsFailedToFetch))
                                )
                            |> ignore
                        )
  • 最后就是 render 函数来渲染我们组件到界面
type tut = string;

type state = 
    | Loading
    | Loaded(array(tut))
    | Error;
type action = 
    | TutsFetch
    | TutsFetched(array(tut))
    | TutsFailedToFetch;

module Decode = {
    let tuts = json: array(string) =>
        Json.Decode.(
            json |> field("messages",array(string)) |> Array.map(_, tut => tut)
        )
}



let component = ReasonReact.reducerComponent("TutListComponent");

let make = _children => {
    ...component,
    initialState: _state => Loading,
    reducer: (action, _state) =>
        switch (action) {
        | TutsFetch => 
            ReasonReact.UpdateWithSideEffects(
                Loading,
                (
                    self =>
                        Js.Promise.(
                            Fetch.fetch("http://localhost:4600/get_tuts")
                            |> then_(Fetch.Response.json)
                            |> then_(json =>
                                json
                                |> Decode.tuts
                                |> (tuts => self.send(TutsFetched(tuts)))
                                |> resolve
                            )
                            |> catch(_err => 
                                    Js.Promise.resolve(self.send(TutsFailedToFetch))
                                )
                            |> ignore
                        )
                ),
            )
        | TutsFetched(tuts) => ReasonReact.Update(Loaded(tuts))
        | TutsFailedToFetch => ReasonReact.Update(Error)
    },
    didMount: self => self.send(TutsFetch),
    render: self =>
    switch (self.state) {
    | Error => <div> (ReasonReact.string("An error occurred!")) </div>
    | Loading => <div> (ReasonReact.string("Loading...")) </div>
    | Loaded(tuts) =>
      <div>
        <h1> (ReasonReact.string("tuts")) </h1>
        <p> (ReasonReact.string("Source: ")) </p>
        <a href=""></a>
        <ul>
          (
            Array.map(tuts, tut =>
              <li key=tut> (ReasonReact.string(tut)) </li>
            )
            |> ReasonReact.array
          )
        </ul>
      </div>
    },
};

相关文章

网友评论

    本文标题:极速开发 React — Reason 2

    本文链接:https://www.haomeiwen.com/subject/ztycmqtx.html