Having trouble applying styles to a component using forwardRef

I'm relatively new to React and still trying to wrap my head around the component's lifecycle. However, the issue at hand is proving to be quite perplexing.

One thing that confuses me is why adding "setState(10);" causes the style of the "Test" component to revert back to its default value, while the

<div ref={ref2}>Hi</div>
keeps its style unchanged (see image below).

I understand that calling "setState(10);" triggers a re-render, but what I can't comprehend is why the style of the "Test" component resets to its default state.

Additionally, please disregard the "practical use" of using setState(10) - I know it serves no purpose as it's never utilized. I also understand that including "state" as a useEffect dependency can resolve this issue. However, my main concern is understanding the reason behind the component's style reverting to its default values.

import React, { useEffect, useState, useRef } from "react";

export default function App() {
  const [state, setState] = useState();
  let ref1 = useRef();
  let ref2 = useRef();
  useEffect(() => {
    console.log("useEffect called ", ref1.current);
    ref1.current.style.backgroundColor = "red";
    ref2.current.style.backgroundColor = "green";
    setState(10);
   // }, [state]);
  }, []);

  const Test = React.forwardRef((props, ref1) => {
    console.log("test called - rendering webpage", ref1.current);
    return (
      <div ref={ref1} {...props}>
        HI from Test{" "}
      </div>
    );
  });

  return (
    <div className="App">
      <Test ref={ref1} />
      <div ref={ref2}>Hi</div>
    </div>
  );
}

Console output

test called - rendering webpage undefined
useEffect called <div style="background-color: red;">HI </div>
test called - rendering webpage <div style="background-color: red;">HI </div>

Answer №1

The disappearance of the style is due to your Test component being defined inside your App component. This means that every time App renders, a new component type named Test is created. Although the content of the component remains the same, react recognizes it as a new type and replaces the old one. Consequently, any changes made to the previous component are lost.

To resolve this issue, you should move Test outside of App. By doing so, the component is defined only once and will not be remounted with each render.

export default App() {
  // ...
}

const Test = React.forwardRef((props, ref1) => {
  // ...
})

This adjustment should prevent the reset and allow you to use refs effectively, although I advise against using refs for styling. While refs can be necessary at times, the recommended approach for styling a component is through the style prop. If styling needs to be changed dynamically, utilize a state variable to control the style prop instead.

If you directly manipulate the style with javascript like

ref1.current.style.backgroundColor
, react cannot register these changes. As a result, react may override or skip updating styles that were modified manually.

export default function App () {
   const [colored, setColored] = useState(false);
   useEffect(() => {
     setColored(true);
   }, [])

   return (
    <div className="App">
      <Test style={colored ? { backgroundColor: "green" } : undefined} />
      <div style={colored ? { backgroundColor: "red" } : undefined}>Hi</div>
    </div>
  );
}

// Not essential anymore, but left for completeness
const Test = React.forwardRef((props, ref) => {
  return (
    <div ref={ref} {...props}>
      HI from Test
    </div>
  );
});

Answer №2

import React, { useEffect, useState, useRef } from "react";

export default function App() {
  const [state, setState] = useState();
  let ref1 = useRef();
  let ref2 = useRef();
  useEffect(() => {
    console.log("useEffect called ", ref1.current);
    ref1.current.style.backgroundColor = "red";
    ref2.current.style.backgroundColor = "green";
    setState(10);
    // }, [ref.current]);
  }, [state]);

  const NewComponent = React.forwardRef((props, ref1) => {
    console.log("NewComponent called - rendering webpage", ref1.current);
    return (
      <div ref={ref1} {...props}>
        Greetings from NewComponent{" "}
      </div>
    );
  });

  return (
    <div className="App">
      <NewComponent ref={ref1} />
      <div ref={ref2}>Hello</div>
    </div>
  );
}

This issue occurs because when the state is updated, the entire component is re-rendered. The useEffect hook only runs once on componentDidMount, so the new reference you get is not updated. To fix this, you should use the state as a dependency of the useEffect.

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

How does the pagination feature in MUI Table handle navigating to the previous page?

I'm looking at this example from the MUI website: https://codesandbox.io/s/3sjxh?file=/demo.js:8248-8255 I'm perplexed by how onPageChange is able to handle both navigating to the previous and next page seamlessly. <TablePagination ...

How do these techniques vary within the classroom setting?

I'm fresh to diving into the realm of react and I find myself puzzled by the nuances between these two class methods doSomething=()=>{ console.log("Something") } and doSomething() { console.log("Something") } At first glance, they appear ...

Modifying the appearance of select components in React MUI using CSS

Can someone help me modify the appearance of the react material UI select component to match this design: I have already applied the following CSS styling: const styles = { width:'250px', border:'1px solid gray', borderBot ...

Error message encountered: Missing property status in TypeScript code

An error occurs in the refetchInterval when accessing data.status, with a message saying "property status does not exist" chatwrapper.tsx const ChatWrapper = ({ fileId }: ChatWrapperProps) => { const { data, isLoading } = trpc.getFileUploadStatus.use ...

Choose the number that is nearest to the options given in the list

I am faced with a challenge involving a list of numbers and an input form where users can enter any number, which I want to automatically convert to the closest number from my list. My list includes random numbers such as 1, 5, 10, 12, 19, 23, 100, 400, 9 ...

What is the best way to set up a session in a Next.js project?

I am currently utilizing Next js for my project development. I've successfully crafted a unique signup form within the platform where users can input their email and password, followed by an OTP being sent to their email address for verification purpo ...

Refreshing HTML content using event delegation in JavaScript

Currently, I am attempting to dynamically load additional HTML content onto my webpage when a button is clicked. Here is the code that I have implemented so far: Main HTML Code: <div class="row" id="gallery-wrapper" > <di ...

Combining the power of jQuery, PHP, JavaScript, and the popular WordPress platform, let's unlock

After going through numerous attempts to find answers for similar issues, I'm unable to get any of the suggested solutions to work. My WordPress site requires a plugin that utilizes jQuery. The main file for my plugin is located at wp-content/plugins ...

struggling to show API response in Redux-React due to technical challenges

Hello everyone, I'm currently delving into the world of redux-react for the first time and facing a challenge with displaying data from my API on the browser. Can anyone lend a hand? Below you'll find snippets of my code. ##slice file export con ...

Is there a method in AngularJS to have $http.post send request parameters rather than JSON?

I have come across some older code that utilizes an AJAX POST request using jQuery's post method. The code looks something like this: $.post("/foo/bar", requestData, function(responseData) { //do stuff with response } The request ...

Ensure the date is displayed in the format of dd-mm-yyyy when using the input type=date

Here is the code I am currently using : <input type="date" class="form-control" id="training_date" name="training_date" placeholder=" select" value="" onfocus="(this.type='date')" onfocusout="(this.type='date')" max=<?php echo ...

Modifying a gridview cell through a Modal popup that is displayed using the rel attribute

I have successfully implemented a modal dialog using CSS and the rel="#showEditModal" attribute of a button. This enabled me to add values to the database and update the gridview effectively. However, I am now facing a challenge where I need to be able to ...

What is the best way to cut and combine multiple array elements in the right positions?

let result = response.data; console.log(result); const newTemp = result.ssps_with_scated.splice(5,1).concat(result.ps_with_ed.splice(2,1))[0]; result.ps_with_ed.push(newTemp); After multiple attempts, I finally achieved my goal. However, the array values ...

Steps for implementing a reset button in a JavaScript slot machine game

I need assistance with implementing a reset button for my slot machine game prototype written in JS. I attempted to create a playAgain function to restart the game by calling the main game function, but it's not working as expected. Do I need to pass ...

Ensuring the container height remains consistent with fluctuating content dimensions

Imagine a container with content, where the container's width is fixed but its height adjusts based on its inner content. Initially, when the content causes the container to be a specific height, the challenge arises in shrinking the inner elements w ...

Client-side filtering for numerical columns using the Kendo UI Grid widget

In my Kendo UI grid widget, I have a model schema set up for a field like this: RS_LookBackDays: { type: "number", editable: true }, The columns configuration for the same field looks like this: { field: "RS_LookBackDays", title: "Rate Schedule – # Lo ...

What could be the reason for the malfunction of the select (mongoose query)?

I'm trying to retrieve a User's highest score post. To accomplish this, I am querying the Post model and looking for posts where their user._id matches the author in the post. Everything is functioning correctly in this regard. However, my goal ...

Should we integrate sailsjs with reactjs or reactjs with sailsjs? What steps can be taken to achieve this integration?

Currently, I am using SailsJS as my web API and ReactJS for the frontend. Can someone please guide me on how to integrate one into the other seamlessly? I am a beginner in this field, so feel free to highlight any mistakes I may have made. ...

External CSS file for Demandware platform

My boss was supposed to train me this year on demandaware knowledge, but ended up quitting, leaving me in the dark. I am scheduled to attend workshops later this year, but for now I am relying on Google and stackoverflow for guidance. Currently, I am wor ...

Troubleshooting Material-UI Menus

I need the menu to adjust its height dynamically as the content of the page increases vertically. Even though I have applied "height:100%" in the styles, it doesn't seem to work. Can anyone assist with this issue? Here is the code snippet: import R ...