I am facing a problem with React Hooks useRef where I am unable to retrieve the updated state value

Trying to use useRef with React hooks, I encountered an issue where the state of the child component changes when calling the setAccountVal method, but upon alerting the value it remains as "Ege". Any ideas on how to resolve this?

    import React, { useState, useRef, useImperativeHandle, useEffect, forwardRef } from "react";
interface A {
    name?: string;
}

const Child = forwardRef((props: A, ref) => {
    const [acc, setAcc] = useState("Ege");
    useImperativeHandle(ref, () => ({
        getAlert(value: string) {
            alert("getAlert from Child===>" + value);
        },

        setAccountVal(val: string) {
            setAcc(val);

        },
        acc
    }));

    useEffect(
        () => {
            debugger;
            setAcc(props.name || "dummy");
            console.log(acc + " --");
        },
        [props.name]
    );

const changeState = (e:React.FormEvent<HTMLInputElement>)=>{
    setAcc(e.currentTarget.value);
}


    return <input onChange={changeState}></input>;
})
function App() {
    let [name, setName] = useState("Nate");

    let nameRef = useRef<any>(null);

    const submitButton = () => {
        debugger;
        const comp = nameRef.current;
        comp.setAccountVal("Mahmut");
        comp.getAlert(comp.acc);
    };

    return (
        <div className="App">
            <p>{name}</p>
            <div>
                <button type="button" onClick={submitButton}>
                    Submit
        </button>
                <Child ref={nameRef} />
            </div>
        </div>
    );
}

export default App;

Even though I am able to see the desired result when calling a normal method, there seems to be a problem where the new state value is not reflected when accessing the acc state from the parent. It still displays the old initial state value ("Ege").

Edit : Actually what i want to do is below

//Child component with forwardRef
const [account, setAccount] = useState("defaultAccount");
const [branch, setBranch] = useState("defaultBranch");
const [person, setPerson] = useState("defaultPerson");

useImperativeHandle(ref, () => ({
    selectedAccount: account,
    selectedBranch: branch,
    selectedPerson: person
}));


//Parent component
const childComponentRef = useRef(null);
//Is it possible to change child component's state? Is it allowed?
childComponentRef.current.selectedAccount = "new account";
childComponentRef.current.selectedBranch = "new branch";
childComponentRef.current.selectedPerson = "new person";

alert(childComponentRef.current.selectedAccount);
alert(childComponentRef.current.selectedBranch);
alert(childComponentRef.current.selectedPerson);

//We can change these variables but child component does not rerender with new values.

Ok! I've found the solution. When i use the ref variables with getter setter now i can set also get the current values with useRef!!

//Child component with forwardRef
const [account, setAccount] = useState("defaultAccount");
const [branch, setBranch] = useState("defaultBranch");
const [person, setPerson] = useState("defaultPerson");

useImperativeHandle(ref, () => ({
    **get account(){
     return account;
    },
    set account(val : string){
    setAccount(val);
    },**
    selectedBranch: branch,
    selectedPerson: person
}));


//Parent component
const childComponentRef = useRef(null);
//Is it possible to change child component's state? Is it allowed?
childComponentRef.current.selectedAccount = "new account";
childComponentRef.current.selectedBranch = "new branch";
childComponentRef.current.selectedPerson = "new person";

alert(childComponentRef.current.selectedAccount);
alert(childComponentRef.current.selectedBranch);
alert(childComponentRef.current.selectedPerson);

//We can change these variables but child component does not rerender with new values

Detailed Demo :

https://codesandbox.io/s/69p5m5j93 .

Answer №1

The reason for the issue is that you are using useImperativeHandle without specifying any inputs, causing the functions to not be updated. To resolve this, simply include acc as an input parameter like shown below:

useImperativeHandle(ref, () => ({
  getAlert(value: string) {
    alert("getAlert from Child===>" + value);
  },

  setAccountVal(val: string) {
    setAcc(val);

  },
  acc
}), [acc]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Capture Video on iOS devices using the MediaRecorder API and display it using HTML5 Video Player

Issue: I am facing an issue where I cannot record video or get a video stream from the camera on iOS through my Angular web application built using ng build. Investigation: In my investigation, I explored various websites that discuss Apple iOS features ...

Tips for displaying field options after typing parentheses in TypeScript in Visual Studio Code

Whenever the letter "b" is typed, the suggestion of "bar" appears. However, I would prefer if the suggestions show up immediately after typing the brackets. https://i.stack.imgur.com/OFTO4.png ...

Using react-confetti to create numerous confetti effects simultaneously on a single webpage

I'm looking to showcase multiple confetti effects using the react-confetti library on a single page. However, every attempt to do so in my component seems to only display the confetti effect on the last element, rather than all of them. The canvas fo ...

Webpack 4.1.1 -> The configuration.module contains a property 'loaders' that is unrecognized

After updating my webpack to version 4.1.1, I encountered an error when trying to run it: The configuration object is invalid. Webpack has been initialized with a configuration that does not match the API schema. - The 'loaders' property in ...

Unable to combine mui theme with emotion css prop

I recently made the switch from overwriting styles in my styles.css file with !important to using emotion css prop for implementing a dark theme in my web app. Below is the code snippet from App.tsx where I define my theme and utilize ThemeProvider: const ...

Encountering the error message "BarChart in react.js is not iterable"

I encountered an issue with the BarChart component: An error message saying "undefined is not iterable!" appeared. The API response I received looks like this: { "saleCharts": [ { "priceSum": 0, "categoryName&q ...

Formik is being utilized to transform an uncontrolled input into a controlled input within a component

While working with a form using Formik, Yup, and NextUi v2 Inputs, an issue arises when typing in one of the inputs that triggers a warning in the console: A component is changing an uncontrolled input to be controlled. This warning is usually due to the ...

Combining Axios with repeated promises

I am facing an issue with a loop in my GET request on the axis, and I cannot figure out why. const [ state, setState ] = useState<any[]>([]); ids.forEach((id) => { getData(id) .then((smth: Map<string, any>[]) => getNeededData ...

Please refrain from clearing the text field as it will delete the input value

I feel like I must be overlooking something really minor because I just can't seem to find it! I've been attempting to sanitize the text input by setting the state to ('') and while it clears the variable, the HTML input keeps displayi ...

The Next.js dynamic route in production is displaying a 403 error instead of the expected 404. What might be causing this issue?

Whenever I attempt to access https://site.con/categories/, I am greeted with a 403 Forbidden error. However, if I visit https://site.con/categories/sport, everything works perfectly fine, and all other routes function properly. What could potentially be ca ...

React Native: Once a user has successfully logged in, I would like the app to automatically direct them to the "Home" screen

After a user signs in, I would like my app to navigate home. However, it seems this is not working because the roots have not been updated. You can view the App code here to get a better understanding of what I am trying to communicate. What is the most e ...

What is the best way to handle "passive event listeners" in reactjs when using event.preventDefault with an onWheel event?

My current challenge involves attempting to preventDefault within an onWheel event in order to enable users to horizontally scroll on specific elements rather than just vertically. However, whenever I try to use e.preventDefault, I am consistently met with ...

Docz: Utilizing Typescript definitions for props rendering beyond just interfaces

We are currently using Docz to document our type definitions. While it works well for interfaces, we've run into an issue where rendering anything other than interfaces as props in Docz components doesn't seem to display properly. I'm seeki ...

React Material-UI eliminates the 'content' property from the CSS pseudo-element

Creating a React MUI Box and styling it like this: <Box id='my-box' sx={{ '&::before': { content: 'Yay! ', backgroundColor: 'red' } }} >Life is beautiful</Box> However, duri ...

Enhancing the security of various components by utilizing secure HTTP-only cookies

Throughout my previous projects involving authentication, I have frequently utilized localstorage or sessionstorage to store the JWT. When attempting to switch to httpOnly secure cookies, I encountered a challenge in separating the header component from th ...

"The Material UI date picker is encountering an issue with the error prop, which is being evaluated

I have developed a date picker that utilizes the Jalali calendar. While attempting to pass error checking using the error prop in the following code: <LocalizationProvider dateAdapter={AdapterJalali}> <MobileDatePicker label={lab ...

What sets apart Material UI's gutterBottom from a paragraph?

Can you explain the distinction between these two options? While exploring the Typography Component API, I noticed that both the gutterBottom and paragraph props seem to serve the same purpose. If set to true, the margin bottom will be 0. You can find mor ...

Implement Google Analytics tracking in Next.js application using the next-redux-wrapper library

I've successfully developed a nextjs app with redux wrapper. class MyApp extends React.Component<AppProps> { public static getInitialProps = wrapper.getInitialAppProps(store => async ({ Component, ctx }) => { Now I'm in the p ...

Changing the dropdown icon in Autocomplete with Material-UI: A Step-by-Step Guide

Is it possible to change the icon for the open/close dropdown list without affecting the functionality? I attempted to use endAdornment but lost functionality for both remove and open/close icons. I simply want to replace Material-UI's custom arrow w ...

The type 'Store<unknown, AnyAction>' is lacking the properties: dispatch, getState, subscribe, and replaceReducer

I have configured the redux store in a public library as follows: import { configureStore } from '@reduxjs/toolkit'; import rootReducer from '@/common/combineReducer'; import { createLogger } from 'redux-logger'; import thunk ...