useRef
useRef有點類似Vue中的ref,用來存取實際DOM元素,可以參考官網的解說。
useRef、forwardRef
這邊使用useRef、forwardRef來存取子元件DOM。
//父元件 form
import { useRef } from 'react'
import classes from './MealItemForm.module.css'
import Input from '../../UI/Input'
const MealItemForm = (props)=>{
const amountInputRef = useRef()
const submitHandler = event=>{
event.preventDefault()
}
return (
<form className={classes.form} onSubmit={submitHandler}>
<Input
ref={amountInputRef}
label={'Amount'}
input={{
id: 'amount_' + props.id,
type:"number",
}}
/>
<button>+ Add</button>
</form>
)
}
export default MealItemForm
子元件使用forwardRef讓父元件可以取到子元件的DOM,子元件的參數除了props,會在多接收一個ref的參數。
import React from 'react'
import classes from './Input.module.css'
const Input = React.forwardRef((props, ref)=>{
return (
<div className={classes.input}>
<label htmlFor={props.input.id}>{props.label}</label>
<input {...props.input} ref={ref}></input>
</div>
)
})
export default Input
useImperativeHandle
useImperativeHandle可以從子元件傳遞自定義內容。使用方式必須和useRef、forwardRef一起使用。
import React {useImperativeHandle, forwardRef, useRef}from 'react'
import classes from './Input.module.css'
const Input = forwardRef((props, ref)=>{
const inputRef = useRef()
const activate = ()=> {
inputRef.current.focus()
}
useImperativeHandle(ref, ()=>{
focus: activate
})
return (
<div className={classes.input}>
<label htmlFor={props.input.id}>{props.label}</label>
<input {...props.input} ref={ref}></input>
</div>
)
})
export default Input
父元件就可以透過綁定的ref去取到子元件剛剛給他的focus函式。
//父元件 form
import { useRef } from 'react'
import classes from './MealItemForm.module.css'
import Input from '../../UI/Input'
const MealItemForm = (props)=>{
const amountInputRef = useRef()
const submitHandler = event=>{
event.preventDefault()
amountInputRef.current.focus()
}
return (
<form className={classes.form} onSubmit={submitHandler}>
<Input
ref={amountInputRef}
label={'Amount'}
input={{
id: 'amount_' + props.id,
type:"number",
}}
/>
<button>+ Add</button>
</form>
)
}
export default MealItemForm