26. Redux 的用途 & 入门实作 (下)

这篇来把上一篇跳过的action补上,然後会补充一点之前没讲过的super()和React Refs。

上一次完成到建立store到显示资料,今天会使用action操作资料!

实作步骤


首先,新增要使用的class component。

class AddContact extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault();
  };
  render() {
    return (
      <div className="box">
          <form onSubmit={this.handleSubmit}> 
            <div className="field">
            <label className="label">Name</label>
            <div className="control">
              <input
                className="input"
                type="text"
                placeholder="John Doe"
              />
            </div>
            </div>
            <button type="submit" className="button">
              Add contact
            </button>
          </form>
      </div>
    );
  }
}

写完component,要记得渲染到画面上:

class App extends React.Component {
  render() {
    return (
      <section className="section">
        <h1 className="title">Contacts</h1>
        <AddContact/>   // 加入AddContact元件
        <Contacts
          contacts={this.props.contacts}
        />
      </section>
    );
  }
}

这里先完成输入框的外观,接下来要慢慢完成实际的作用。

onSubmit={this.handleSubmit}是用来防止提交表单,
我自己习惯写到form就会先加preventDefault(),不然按到送出页面会跑掉,有点麻烦。

action


action 是一种 JS的物件,代表 state 要执行的改变。

Action 是让 data 进到 store 的唯一方式。任何 data,无论是从 UI 事件、网路 callback、或其他来源,像是 WebSocket 最後都需要作为 action 被 dispatch(派遣;发送)。

  • action creator
    产生 action 的 function,呼叫 action creator 会产生一个 action,但并不会 dispatch action。如果要实际进行操作,必须呼叫 store 的 dispatch function。

进到范例,我们先指定一个action要执行的动作,在程序码加入这几行:

// 要对state执行的动作
const actions = {
  addContact: name => {  // 新增一个叫做addContact的action,参数为name
    return {
      type: "ADD_CONTACT",   // 先指定action的type
      id: uuid.v4(),
      name
    };
  }
};

addContact会回传属性typeid和传入的参数name
action必须指定一个type,这里指定的type名为"ADD_CONTACT"。

id和name就是我们一开始的store里的资料格式!
id一样会随机产生,name则是输入框输入的值。

然後看到上次已经完成的reducer,在里面的switch多设定一种情况(case):

const reducer = (state = {}, action) => {
  switch (action.type) {
    // 新增情境
    case "ADD_CONTACT":         
      const { name } = action;   // 取得action里的name property    
      return [{ name }, ...state];   // 回传action的阵列
    default:
      return state;
  }
}

因为要把action传给component,这里使用bindActionCreators

import { bindActionCreators } from Redux

const mapDispatchToProps = dispatch => {
    return bindActionCreators(actions, dispatch);
}
  • bindActionCreators
    bindActionCreators 只有一种使用情境: 想将 action creator 传递给一个 component,但不打算把 dispatch 或 store 传递进去。
    action creator 会被包进一个 dispatch 呼叫里面,所以它们可以直接被呼叫。

记得还要连结component和写好的 mapDispatchToProps才有用:

// AppContainer接收connect处理好 mapStateToProps,mapDispatchToProps和 App的结果
const AppContainer = connect(mapStateToProps,mapDispatchToProps)(App);

这样就可以把写好的actions传进component使用了!

<AddContact addContact={this.props.addContact}/>

到这里是action的定义到设定,接下来会真正对资料进行操作。


回到文章最开始写的component,

最後要去得实际input的值,把他新增到store。


class AddContact extends React.Component {
  // 建构子
  constructor(props) {
    // calls the parent constructor(= React.Component).
    super(props);  
    // 产生一个可以储存 textInput DOM element 的 ref
    this.textInput = React.createRef();
  }
  handleSubmit = (event) => {
    event.preventDefault();
    // 利用「current.value」来取得 DOM 节点的值
    this.props.addContact(this.textInput.current.value);
  };
  render() {
    ...
      <input
        className="input"
        type="text"
        ref={this.textInput}    // 指定ref的值
        placeholder="John Doe"
      />
  }
}

这样应该就能成功新增资料了!

附上 codepen完整程序码

( 如果对super.createRef()不熟悉,後面写的比较详细,可以看完再回来理解。)

super(props)

如果没有初始化state和绑定方法(methods),就不需要执行建构式(constructor)。

If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.

必须在叙述式前呼叫super(props),否则this.props会是undefined,可能导致错误。

you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor

使用建构式有两个目的:

  1. 藉由指派一个物件(object)给this.state,作为local state初始化。
  2. 将事件处理器(event handler)绑定给一个实例(instance)。

不能在建构式里执行 setState()

super 关键字必须出现在this 关键字之前使用,super 关键字也可以使用在呼叫函式与父对象。

Refs & DOM

Ref 提供了一种可以取得 DOM 节点或在 render 方法内建立 React element 的方式。

Ref 的值会根据节点的类型而有所不同:

  • 在 HTML element 上使用 ref 参数时
    React.createRef() 建立 ref 会取得 HTML element 底下的 DOM element 来做为它的 current 属性。
  • 在客制化的 class component 使用 ref 参数时
    ref 取得 被 mount 的 component 上的 instance 来当作他的 current。
  • function component 因为没有 instance,不能使用 ref。

【如内文有误还请不吝指教>< 并感谢阅览至此的各位:D 】

参考资料

---正文结束---

昨天临时有事没办法写文,竟然在倒数5天失败了QQ 但我还是会把文章写完的!


<<:  Day 24 权限宝石:IAM 权限管理 架构解析

>>:  Day14-Webhook 实作(三)LINEBot 之 MessageBuilder(I)

深入理解React Diff算法

点击进入React源码调试仓库。 上壹篇React状态计算解密 之後,我们来分析壹下Diff的过程。...

[Day27]用Canvas打造自己的游乐场-labyrinth 键盘控制角色

今天要来加入玩家角色,以及用键盘来控制角色 // 玩家 var player_x; var play...

敏捷开发 组别

敏捷开发 https://wolkesau.medium.com/敏捷开发-1afc1cd6edf ...

网页常用单位-30天学会HTML+CSS,制作精美网站

设置CSS样式大小时,会使用到各种不同的单位,尤其现在都制作响应式网站,用错单位,就会针对不同尺寸调...

【Day 29】- 应对反爬虫技术-综合篇

前情提要 昨天跟各位读者简介了反爬虫技术中,较常出现的验证码之应对方法。 开始之前 今天要跟各位介绍...