---
# System prepended metadata

title: j104 以 React 封裝 - 以表單為例

---

j104 以 React 封裝 - 以表單為例
===

## 摘要
> 這份文件旨在封裝 j104 React 元件。因為使用 React 時，許多同樣的 j104 code，散落在每一個 single page 頁面。要維護同一個零件時，需要去各個地方修改。封裝後引入、維護上比較方便，例如說 j104 有upgrade 產生異動時，整個專案只需要改一個地方。

## 目錄

[TOC]

---

## 一. 情境：

現在有三個表單頁面，如下：

![](https://i.imgur.com/hruFswu.png)

假設我決定**三頁**都要使用以下工具、動作：

**A. React single page、
B. j104 form、
C. j104 tip、
D. 回收 j104**

## 二. 原本的寫法，同樣的 code 散落在每一頁

*註：以下圖中的 code，同一個字色，是代表同樣的 code。以下使用 pseudo code。*

### 步驟1. 我先新增 form：

![](https://i.imgur.com/vYtkx7p.png)

### 步驟2. 然後再新增 tip:

![](https://i.imgur.com/GfF7CyJ.png)

從圖中可以看到許多同樣的 code，散落在每一頁。要維護同一個零件時，需要去各個頁面修改。

## 三. 目標

能不能將同樣的 code，包括起始和回收等，**封裝**在零件裡？這樣就只需要維護同一個零件。


## 四. 方法

* 架構

![](https://i.imgur.com/2j7WcJn.png)

```graphviz
digraph hierarchy {

                nodesep=1.0 // increases the separation between nodes
                
                node [color=Red,fontname=Courier,shape=box] //All nodes will this shape and colour
                edge [color=Blue, style=dashed] //All the lines look like this

                ReactForm->{PageA PageB PageC} // Put them on the same level
}
```

### 步驟1. 定義 React Form、React Tip：

* Form

```
React component Form {

    componentDidMount 
        this.Form = new j104.form(this.formDiv, this.props.option);

    componentWillUnmount
        this.Form.destroy();

    render 
        <div ref={(e) => this.formDiv = e;}}>
            {this.props.children}
        </div>

}
```

* Tip

```
React component Tip {

    componentDidMount 
        this.tip = $(this.tipDiv).tip(this.props.text);

    componentWillUnmount
        this.tip.destroy();

    render <div ref={(e) => {this.tipDiv = e;}} />

}
```

```
React component Tip {

    componentDidMount 
        this.tip = $(this.tipDiv).tip(this.props.text);

    componentWillUnmount
        this.tip.destroy();

    render
        const { className } this.props;
        <div 
            ref={(e) => {this.tipDiv = e;}} 
            className={className ? className : ''}
        />

}
```

### 步驟2. 頁面使用 React Form、React Tip

* Form

```
<Form option={option}>
    <input A />
    <input B />
    <input C />
    <button submit />
</Form>
```

* Tip

```
<Tip text='這是tip' />
```


### 完成後的三個頁面：

![](https://i.imgur.com/pSn9Tig.png)




## 五. 小結
優點是維護性更好：將 j104 元件的起始和回收，結合 React 生命週期，成為一個一個獨立可共用的 j104React 元件。而 j104 有 upgrade 產生異動時，整個專案只需要改一個地方。


## 附錄：

### 1. J104 Form 進階

當 submit 時，不需要 call ajax，只需要取值做處理，這時可以用其他的寫法，其中之一如下：


```
React component Form {

    componentDidMount 
        this.Form = new j104.form(this.formDiv, this.props.options);

    componentWillUnmount
        this.Form.destroy();
        
    getValue
        return this.Form.getValues();
        
    validate
        return this.Form.validate();
        
    success
        this.formDiv.success(text);
    
    error
        this.formDiv.error(text);

    render 
        <div ref={(e) => this.formDiv = e;}}>
            {this.props.children}
        </div>

}
```
use
```
_submit
    this.Form.validate();
    this.Form.getValue();
    this.Form.success(text);

render 
    <Form 
        ref={(e) => this.Form = e;}}
        options={options}
    >
        <input A />
        <input B />
        <input C />
    </Form>
    <button _submit />
```


## 參考資料：
[用 react 的思考方式](https://reactjs.org/docs/thinking-in-react.html)