skip to Main Content

I’m trying to read a value from an input textbox on initial render using useRef but I am getting the following error message:

" ref is not a prop. Trying to access it will result in undefined being returned. If you need to access the same value within the child component, you should pass it as a different prop."

This is my component below:

When I log "name" I get null

const AddProject = () => {
  const refContainer = useRef(null);
  const name = refContainer;
  useEffect(() => {
    console.log(name);
  });
  return (
    <Wrapper>
            <Form>
              <FormRow
                type="number"
                name="noOfChemicals"
                labelText="Number of Chemicals / Work Items"
                onChange={handleChange}
                defaultValue="1"
                ref={refContainer}
              />
            </Form>
    </Wrapper>
  );
};
export default AddProject;

my FormRow component looks like this. I’m trying to pass the ‘ref’ in as a prop.

import React from "react";

const FormRow = ({
  type,
  name,
  labelText,
  defaultValue = "",
  onChange,
  onBlur,
  max,
  ref,
}) => {
  return (
    <div className="form-row">
      <label htmlFor={name} className="form-label">
        {labelText || name}
      </label>
      <input
        autoComplete="off"
        type={type}
        id={name}
        name={name}
        className="form-input"
        defaultValue={defaultValue}
        required
        onChange={onChange}
        onBlur={onBlur}
        max={max}
        min="0"
        ref={ref}
      />
    </div>
  );
};

export default FormRow;

Can anyone assist?

2

Answers


  1. First, you must use the forwardRef function to forward the reference to the child component’s parent DOM element when you pass one to itself.

    const FormRow = React.forwardRef(
      ({ type, name, labelText, defaultValue = "", onChange, onBlur, max }, ref) => {
        return (
          <div className="form-row">
            <label htmlFor={name} className="form-label">
              {labelText || name}
            </label>
            <input
              autoComplete="off"
              type={type}
              id={name}
              name={name}
              className="form-input"
              defaultValue={defaultValue}
              required
              onChange={onChange}
              onBlur={onBlur}
              max={max}
              min="0"
              ref={ref}
            />
          </div>
        );
      }
    );
    

    You must now use useEffect in your AddProject component with the dependency array in order to log the input value following the first render. In order to obtain the real DOM element, you should also access the ref object’s current attribute.

    useEffect(() => {
        console.log(refContainer.current.value);
      }, []);
    
    Login or Signup to reply.
  2. The issue you’re facing is related to how refs are handled in React. When using a ref in a child component like FormRow, it should be forwarded correctly for the ref to work as intended.

    The problem lies in how you’re passing the ref prop in the FormRow component. In functional components, refs should be handled differently compared to regular props. You can’t directly pass the ref prop; instead, you should use React.forwardRef to handle it properly.

    Here’s how you can modify your FormRow component to correctly handle the ref:

    import React from "react";
    
    const FormRow = React.forwardRef(
      (
        {
          type,
          name,
          labelText,
          defaultValue = "",
          onChange,
          onBlur,
          max,
        },
        ref
      ) => {
        return (
          <div className="form-row">
            <label htmlFor={name} className="form-label">
              {labelText || name}
            </label>
            <input
              autoComplete="off"
              type={type}
              id={name}
              name={name}
              className="form-input"
              defaultValue={defaultValue}
              required
              onChange={onChange}
              onBlur={onBlur}
              max={max}
              min="0"
              ref={ref}
            />
          </div>
        );
      }
    );
    
    export default FormRow;
    

    Then, in your AddProject component, you can continue using useRef as you were doing:

      const name = refContainer.current?.value; // Access value using current
      useEffect(() => {
        console.log(name);
      }, [name]); // Include name in dependency array to log changes
    
    

    This change should allow you to properly access the value of the input using the useRef hook within your AddProject component.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search