0

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?

2 Answers 2

1

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.

  1. App.js pass initialValue to CustomInput
<CustomInput
    initialValue={"abc"}
    label="First name"
/>
  1. In CustomInput pass initialValue prop to useForm hook as an argument.
const { value, onInputHandler, onBlurHandler } = useForm(props.initialValue); 
  1. Set the initialValue as the value in initial state in useForm.
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.

  1. In App.js defines another function that accepts event as an argument.
export default function App() {
  const onInputHandler = (e) => {
    console.log(e);
  };

  return (
    <div className="App">
      <CustomInput
        ...
        onInputHandler={onInputHandler}
        label="First name"
      />
    </div>
  );
}
  1. In CustomInput change the onInput handler like below. You can change the logic as per your needs (I called onInputHandler in useForm and prop).
      <input
        value={value}
        onBlur={onBlurHandler}
        onInput={(e) => {
          props.onInputHandler && props.onInputHandler(e);
          onInputHandler(e);
        }}
        {...props}
      />

Edit festive-architecture-dr64t

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.