Ref
在典型的 React中,props 是 父层与子层唯一的互动方式。藉由使用新的 prop 重新 render 来改变你的子层。
什么时候该使用 Ref
管理 focus、选择文字、影音播放。触发即时的动画与第三方 DOM 函式库整合不要过度使用 Ref
建立 Ref
class Login extends React.Component{ //建立Ref emailRef = React.createRef(); passwordRef = React.createRef(); //存取Ref const formData = { email:this.emailRef.current.value, passwordRef:this.passwordRef.current.value }; render() { return( <input class="input" type="text" placeholder="Email" ref={this.emailRef}/> <input class="input" type="text" placeholder="Password" ref={this.passwordRef} /> ) }};export default Login;
state
重点
通常会在component的 constructor 设定state初始值。1.使用constructor设定初始值
class Like extends React.Component{ constructor() { super(); this.state = { isLike:false; //预设为false } }}
2.使用state设定初始值
class Like extends React.Component{ state = { isLike:false //预设为false }}
要改变state,必须使用setState()。class Like extends React.Component{ //设定预设值 state = { isLike:false, //预设为false const:0 //预设const = 0 } //建立Event Function handleClick() => { //取得当前状况并对状况进行处理 this.setState({ isLike: !this.state.isLike, //取得当前状态并进行反转 const:this.state.const + 1 //取得当前状况并+1 }); //若要取得上一个对象的状态需要使用箭头函数 this.setState(prevState => { return{ count : prevState.const + 2 }; }); }; render() { return( <button className = "button is-fullwidth is-primary" onClick = {this.handleClick}> {this.state.isLike? "No":"Yes"} </button> ) }}
可控组件(Controlled component)与不可控组件(Uncontrolled component)
不可控组件(Uncontrolled component)
如果要写一个 uncontrolled component,你可以使用 ref 来从 DOM 取得表单的资料由Ref取得input的Data,并当form的Submit被触发后进入function "handleSubmit",将Ref中的data取出
(this.input.current.value)
class NameForm extends React.Component{ //建立constructor constructor() { super(); //使用bind複製function handleSubmit并将this(自身class)指定给他,进行this绑定 this.handleSubmit = this.handleSubmit.bind(this); //使用Ref取得input资料 input = React.createRef(); } handleSubmit = (event) =>{ alert('A name was submitted: ' + this.input.current.value); //取消默认行为 event.preventDefault(); } render() { return( <form onSubmit={this.handleSubmit}> <label>Name:<input type="text" ref={this.input} /> </label> <input type="submit" value="Submit" /> </form> ); }};
预设值:在React的render生命週期里,表单的"value attribute"会覆盖掉DOM的值,在使用uncontrolled component会希望表单设定初始值但又在更新后保值不可控制,这种情况可以使用"defaultValue "render(){ return( <form onSubmit={this.handleSubmit}> //使用defaultValue设定表单的value <label> Name:<input defaultValue="Fandix" type="text" ref={this.input} /></label> </form> )}
可控组件(controlled component)
在 HTML 中,表单的 element 像是 "input"、"textarea" 和 "select" 通常会维持它们自身的 state,并根据使用者的输入来更新 state。在 React 中,可变的 state 通常是被定义在 component 中的 state property,并只能以 setState() 来更改期内容。我们可以透过将 React 的 state 变成「单一数据源」让render表单的React component可以掌握使用者的输入当input的值发生改变(触发onChange进入function "handleChange")function会将使用者输入的值利用setState将input的state进行更改,而当onSubmit被触发后进入function handleSubmit再将被改变的state中的Data取出。
class NameForm extends React.Component { //建立constructor constructor() { super(); //绑定function的this this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } //设定state内容 state = { value: "" } handleChange(event) { //变更State的值需要使用setState this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); //取消默认行为 event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label>Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); }}
由于 value attribute 是被设定在input上,显示的 value 会永远是 this.state.value,这使得 React 的 state 成为了资料来源。由于 handleChange 在每一次键盘被敲击时都会被执行,并更新 React 的 state,因此被显示的 value 将会在使用者打字的同时被更新。
处理多个输入
当你需要处理多个 controlled input element,可以在每个 element 中加入一个 name,让 handler function 选择基于 event.target.name 的值进行判断
class Reservation extends React.Component { construtor() { super(); //绑定function的this this.handleInputChange = this.handleInputChange.bind(this); } //设定state内容 state = { isGoing:true, numberOfGuests:2 } handleInputChange = (event) =>{ const target = event.target; const value = target.name === 'isGoing' ? target.checked : target.value; const name = target.name; this.setState({ [name]:value }); } render() { return( <form> <label> Is going: <input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange} /> </label> <br /> <label> Number of guests: <input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange} /> </label> </form> ); }};
当两个input发生改变就会进入function "handleInputChange" 判断event.name是不是input1,若是就更新name = isGoing中的State(isGoing),若不是则更新name = "numberOfGuests"中的State(numberOfGuests)。