Home > Mobile >  Cannot useRef() in functional component. null is not an object
Cannot useRef() in functional component. null is not an object

Time:04-26

I have a functional component which causes the following error:

null is not an object (evaluating 'textInput.current.blur'

I wonder why

import React, { useState, useRef } from "react";
import { TextInput } from "react-native";

const UselessTextInput = ({ hide }) => {
    const [text, onChangeText] = React.useState("Useless Text");
    const textInput = useRef(null);

    const _renderInput = () => {
        if (hide) textInput.current.blur();
        <TextInput
            ref={textInput}
            onFocus={() => ...}
            onChangeText={onChangeText}
            value={text} />

    ...

    return __renderInput();
}

Can anyone explain this behaviour?

CodePudding user response:

If you set a ref to a DOM node using the ref attribute, the ref's current property will have that node only after it's set i.e. in useEffect callbacks or from next renders.

function Counter() {
  const [count, setCount] = React.useState(0);
  const divRef = React.useRef("initval");

  console.log("During Render", divRef.current);

  React.useEffect(() => {
    console.log("Inside useEffect CB", divRef.current); 
  }, []);

  return <button ref={divRef} onClick={() => setCount(count   1)}>{count}</button>;
}

ReactDOM.render(<Counter />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>

Understanding the flow:

  • When useRef is called React returns an object whose current property is set to the initial value provided ("initval" in our case).

  • So, the console log during first render prints the initial value.

  • Then the JSX is returned from the component, which updates the ref and sets it's current property to the DOM node.

  • Then the callback passed useEffect runs and since the ref has already been updated it prints the DOM node.

  • Then in next render (which can be triggered by clicking on the button), again we call useRef and React returns the same object and therefore this time the log during the render prints the DOM node.

CodePudding user response:

use optional chaining to your textInput value

like this : textInput?.current?.blur();

  • Related