这篇来把上一篇跳过的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 是一种 JS的物件,代表 state 要执行的改变。
Action 是让 data 进到 store 的唯一方式。任何 data,无论是从 UI 事件、网路 callback、或其他来源,像是 WebSocket 最後都需要作为 action 被 dispatch(派遣;发送)。
进到范例,我们先指定一个action要执行的动作,在程序码加入这几行:
// 要对state执行的动作
const actions = {
addContact: name => { // 新增一个叫做addContact的action,参数为name
return {
type: "ADD_CONTACT", // 先指定action的type
id: uuid.v4(),
name
};
}
};
addContact
会回传属性type
、id
和传入的参数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);
}
记得还要连结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()
不熟悉,後面写的比较详细,可以看完再回来理解。)
如果没有初始化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
使用建构式有两个目的:
this.state
,作为local state初始化。不能在建构式里执行 setState()
。
super 关键字必须出现在this 关键字之前使用,super 关键字也可以使用在呼叫函式与父对象。
Ref 提供了一种可以取得 DOM 节点或在 render 方法内建立 React element 的方式。
Ref 的值会根据节点的类型而有所不同:
React.createRef()
建立 ref 会取得 HTML element 底下的 DOM element 来做为它的 current 属性。【如内文有误还请不吝指教>< 并感谢阅览至此的各位:D 】
参考资料
---正文结束---
昨天临时有事没办法写文,竟然在倒数5天失败了QQ 但我还是会把文章写完的!
>>: Day14-Webhook 实作(三)LINEBot 之 MessageBuilder(I)
点击进入React源码调试仓库。 上壹篇React状态计算解密 之後,我们来分析壹下Diff的过程。...
今天要来加入玩家角色,以及用键盘来控制角色 // 玩家 var player_x; var play...
敏捷开发 https://wolkesau.medium.com/敏捷开发-1afc1cd6edf ...
设置CSS样式大小时,会使用到各种不同的单位,尤其现在都制作响应式网站,用错单位,就会针对不同尺寸调...
前情提要 昨天跟各位读者简介了反爬虫技术中,较常出现的验证码之应对方法。 开始之前 今天要跟各位介绍...