Am new to react and i have a custom input where am handling the value and input handler via a custom hook but would like to get the value and the input handler to the parent component using the custom input but am stuck on how to achieve this. I have written the following code.
On the custom hook
import {useReducer} from "react";
const INITAL_STATE = {value:'',valid:false,pristine:true, error:''}
const REDUCER_ACTIONS = { input:"INPUT", blur:"BLUR"}
const reducer = (state,action)=>{
if (action.type === REDUCER_ACTIONS.input){
return {...state, value: action.value}
}
if (action.type === REDUCER_ACTIONS.blur){
return {...state, pristine: false}
}
return INITAL_STATE;
}
const useForm = () => {
const [inputState, dispatch] = useReducer(reducer,INITAL_STATE)
const onBlurHandler = (event) => {
dispatch({type:REDUCER_ACTIONS.blur});
}
const onInputHandler = (event) => {
dispatch({type:REDUCER_ACTIONS.input,value:event.target.value})
}
return {
...inputState,
onBlurHandler,
onInputHandler
}
};
export default useForm;
And for my custom input i have
import useForm from "../../hooks/use-form";
const CustomInput = (props) => {
const {value, onInputHandler, onBlurHandler} = useForm(); //uses custom hook
return <>
<label htmlFor={props.id}>{props.label}</label>
<input value={value} onBlur={onBlurHandler} onInput={onInputHandler}
{...props} />
</>
}
export default CustomInput;
The above custom input has the onInput and onBlur pointing to the custom hooks since i want to reuse the functionality on other input types like select and date pickers without having to duplicate them.
On my parent component am simply calling the Custom input like
function App() {
return (
<div className="container">
<CustomInput onInputHandler={} label="First name"/>
</div>
);
}
export default App;
I would like to pass the onInputHandler and value as a props back to the parent component from the custom input but am stuck on how to do this. How do i proceed?
CodePudding user response:
When you say you need to pass value, I guess you wanted to pass the initial value of the input to CustomInput. To achieve that you can pass another prop.
- App.js pass
initialValuetoCustomInput
<CustomInput
initialValue={"abc"}
label="First name"
/>
- In
CustomInputpassinitialValueprop touseFormhook as an argument.
const { value, onInputHandler, onBlurHandler } = useForm(props.initialValue);
- Set the
initialValueas thevaluein initial state inuseForm.
const useForm = (initialValue) => {
const [inputState, dispatch] = useReducer(reducer, {
...INITAL_STATE,
value: initialValue
});
...
...
}
To pass the onInputHandler as a prop you can check if onInputHandler is available as a prop and call it along with onInputHandler coming from useForm.
- In App.js defines another function that accepts
eventas an argument.
export default function App() {
const onInputHandler = (e) => {
console.log(e);
};
return (
<div className="App">
<CustomInput
...
onInputHandler={onInputHandler}
label="First name"
/>
</div>
);
}
- In
CustomInputchange the onInput handler like below. You can change the logic as per your needs (I called onInputHandler inuseFormandprop).
<input
value={value}
onBlur={onBlurHandler}
onInput={(e) => {
props.onInputHandler && props.onInputHandler(e);
onInputHandler(e);
}}
{...props}
/>
CodePudding user response:
My approach to this will be to simply call the onInputHandler() from hooks and onInputHandler() from the props received from Parent and send the e.target.value as a prop to these functions.
const CustomInput = (props) => {
const { value, onInputHandler, onBlurHandler } = useForm(); //uses custom hook
console.log(value);
const handleInputChange = (e: any) => {
onInputHandler(e);
props.onInputHandler(e.target.value);
};
return (
<>
<label htmlFor={props.id}>{props.label}</label>
<input
value={value}
onBlur={onBlurHandler}
onInput={(e) => {
handleInputChange(e);
}}
{...props}
/>
</>
);
};
export default CustomInput;
And in the parent component we can receive them as props returned from that function and use it according to our requirement.
function App() {
return (
<div className="container">
<CustomInput
label="name"
onInputHandler={(value: string) => console.log("App",value)}
/>
</div>
);
}
export default App;
sandbox link : https://codesandbox.io/s/nifty-lamport-2czb8?file=/src/App.tsx:228-339
