極速開發(fā) React — Reason 2

Speed_Racer_promotional_image.jpg

現(xiàn)在是速度至上的時代,我們必須以一敵百。才能立于不敗之地。

FCJG300-0043.jpg

面對越來越復(fù)雜的業(yè)務(wù)邏輯,我們只能全速向前沖,這一切都需要有技術(shù)作為保障。所以我們需要選擇一個能夠?qū)崿F(xiàn)快速開發(fā)的技術(shù)。
th.jpg

reason react 網(wǎng)址
個人選擇并且推薦使用 reason 來開發(fā)
極速開發(fā) React — Reason 1

  • 更安全,更簡潔的方式去構(gòu)建 React 組件
  • 完全兼容 JSX
  • 類型安全兼容 javascript 編寫的組件
  • 用于一種全新的表述型 API 來描述狀態(tài)管理
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

創(chuàng)建 index.html

我們將架構(gòu)默認的工程文件都刪除,自己來寫一個列表的 demo。先創(chuàng)建一個 index.html。

  • 引入 Index.js 最終 webpack 打包后會引用 index.js
  • id 為 app 的 div,我們的應(yīng)用都寫在這個 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>

然后創(chuàng)建 re 結(jié)尾的 reason 文件

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

我們這里可能需要使用 bs-json 和 bs-fetch,我們可以用 npm 來安裝一下這兩個庫,或者說是 reason 的模塊。然后需要 bsconfig 文件添加依賴,這樣我們就可以在工程中使用這兩模塊。

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

我這里用 python flask 寫了一個服務(wù),返回值為


rr_002.JPG
  • 我們先定義一個數(shù)據(jù)結(jié)構(gòu),用 type 定義 tut 類型 string
    我們可以定義 type 定義的數(shù)據(jù)類型,reason 是一種類型的語言,這對沒有類型的 javascript 是一個強大的支持。
type tut = {title:string, body:string}

我們這里根據(jù)官網(wǎng)的 demo 就先簡單地定義為 string

type tut = string;
  • reason react 給我們提供兩種創(chuàng)建組件模板
  1. statelessComponent
  2. reducerComponent
    這里我們創(chuàng)建 reducerComponent 類型組件
  • 創(chuàng)建 state 狀態(tài) 這也是 ocaml 的語法,應(yīng)該算是類型匹配吧,有了這個就可以保證我們在做分支語句不會漏掉某些可能性。action 定義方式也是一樣,有關(guān) action 和 state 如果大家還沒有接觸過可以看一看 redux,以后我會分享的。
type state = 
    | Loading
    | Loaded(array(tut))
    | Error;
  • 定義模塊 Decode
    我們可以在模塊定中定義類型和方法,這里我們定義了一個 tuts 的方法,用于解析服務(wù)端返回的數(shù)據(jù),然后我們使用 Json 模塊的 Decode 方法,這個 Json 模塊需要我們手動引用一下。|> 如果用過 linux 的腳本或者寫過 powershell 的程序員可能不會陌生,這是鏈式操作。我們接受返回 json -> 然后獲取 messages 字段的值類型為 string 的數(shù)組 -> 然后對數(shù)組進行映射。
module Decode = {
    let tuts = json: array(string) =>
        Json.Decode.(
            json |> field("messages",array(string)) |> Array.map(_, tut => tut)
        )
}


- **make**
是讓我們在編譯時生產(chǎn) component 的方法。

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

然后就是 reducer 這純函數(shù),最近然后 mvi 模式,再次開始研究 reducer,reduce 我還是在學(xué)習(xí) redux + react + rxjs 時學(xué)習(xí)過,為了理解也花費不少精力。這里簡單介紹一下,畢竟 reduce 不是我們今天的重點。reduce 是一個純函數(shù),接受 action(動作)返回一個新的 state。然后我們 reducer 中根據(jù) action 進行分支更新我們狀態(tài)。這里我發(fā)現(xiàn)沒有用引入 redux 卻做了 redux 事情,代碼表意也挺好,給 reason 一個贊。

  • 在說一下 Promise ,對于了解 es6 前端 promise 應(yīng)該不是很陌生,這里同樣使用管道符來進行處理。
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 函數(shù)來渲染我們組件到界面
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>
    },
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容