My component in my modal is rerendering twice

Asked
Active3 hr before
Viewed126 times

10 Answers

twicemodalcomponent
90%

UseEffect(), if not specified, will be called for every prop/state update. You should specify in the useEffect when the call should be made using an additional parameter,If you write it like this, your effect will be only called when the shouldUpdateVar variable is changing.,You can see it in the docs useEffect conditional

UseEffect(), if not specified, will be called for every prop/state update. You should specify in the useEffect when the call should be made using an additional parameter

useEffect(() => {
   dispatch(yourAction());
}, [shouldUpdateVar]);
88%

We can start by running a brand new CRA installation:,Function component bodies,What will happen though when we use a React hook and add some state management to our function component?

We can start by running a brand new CRA installation:

npx create - react - app my - app && cd my - app
load more v
72%

Here is a simplified version of the parent component using the modal dialog:,Something where the dialogprops and hide/show functions are encapsulated within the button and hidden from the parent component:,The Field component uses several hooks of its own. It is the last console log displaying '*** Field.render' that I see twice. Here is a simplified version of the Field component:

import React from 'react';
import { useModal } from "react-modal-hook";
import Form from './Form';
import Form from './Field';
import Form from './Button';
import FindDialog from './FindDialog';

let dialogprops = {};
function setDialogProps(props) {
    dialogprops = props;
}

export default function WebForm(props) {
const [showDialog, hideDialog] = useModal(() => FindDialog(dialogprops));
return (
   <Form>
      <Field label="A Field" id="field1"/>
       ...
      <Button source="/img/add.png" hovertext="Add a record" 
            onClick={(context)=>{ 
               setDialogProps({
		hideDialog:hideDialog,
		title:"Find a Record",
		onSelect: (selection) => { console.log('Selected:'+selection); }
	       });
	       showDialog();
            }}
      />
   </Form>
)
load more v
65%

if you used create-react-app and run your app with yarn start you will see the following output in the browser console:,Many developer have implemented a similar functional component and have seen this behavior. Some have even opened a bug report in the official React repository.,Switching to Class Comonents is no difference - you will see the effect even without any state management:

Copy1function App() {2    const [click, setClick] = React.useState(0);34    console.log('I render 😡', click);5    return (6        <div>7            <button onClick={() => setClick(click => click + 1)}>8                Clicks: {click}9            </button>10        </div>11    )12}
load more v
75%

Which may cause your app to go through an infinite loop, then crashing.,The render method is required whenever you’re creating a new React component.,The first render gets triggered after the componentWillMount lifecycle.

componentDidMount() {
  this.setState({ ruinPerformance: true });
}

render() {
  return (
    <SubComp>
      <SubComp>
        <SubComp>
          <SubComp>
            Hello world :)
          </SubComp>
        </SubComp>
      </SubComp>
      <SiblingComp />
    </SubComp>
  );
}
load more v
40%

Is it noticeable? Does the component render empty then flash in the user data?,Nothing inherently bad with that. Deprnding on the structure of your components you could consider putting the if statement in the parent before you give the empty prop.,... then I would merely add the initial state provided previously. However, if the component will indeed grow I would remove the if you have in the render() and replace it with the following:

Example code using local state

componentDidMount() {
    fetch.post('/get-user', data)
    .then(result => {
        this.setState({
            user: result.user
        });
    })
    .catch(err => console.log(err));
}

render() {
    // First render will return an error stating cannot get username from null
    // Reasonable, as the first render, the user object in the state is empty/null
    // Second render after the setState from componentDidMount is where user will have data
    // In order for it to not return an error, I have to specify
    // if (this.state.user) {
    return(
        <div>{this.state.user.username}</div>
    )
}
load more v
22%

React renders your component (calls it),useLayoutEffect, on the other hand, runs synchronously after a render but before the screen is updated. That goes:,The screen is visually updated

useEffect(() => {
   // do side effects
   return () => /* cleanup */
}, [dependency, array]);

useLayoutEffect(() => {
   // do side effects
   return () => /* cleanup */
}, [dependency, array]);
load more v
60%

These examples clarified lot of my questions around the execution flow/re-renders. They also helped in creating a better mental model around building functional components using hooks more efficiently.,This post is a result of my explorations to understand how each built-in hook influences the component re-renders/lifecycle. I’ll share my learnings with detailed examples and also highlight some pitfalls I ran into. This is a long post covering most of the built-in hooks with lot of screenshots and examples. If you are interested in only a specific hook, please go directly from the links below.,useState hook is the primary building block which enables functional components to hold state between re-renders.

Let’s understand the workings of useState with an example. We will implement the Ticker component as per the above sketch. The active ticker which is shown on the UI is stored in a local state using useState hook. Here is the relevant portion of the component (full code here).

const [ticker, setTicker] = useState("AAPL");...
const onChange = event => {
   setTicker(event.target.value);
}...
load more v
48%

We strongly recommend against creating your own base component classes. In React components, code reuse is primarily achieved through composition rather than inheritance.,These methods are called in the following order when an instance of a component is being created and inserted into the DOM:,This lifecycle is invoked after an error has been thrown by a descendant component. It receives two parameters:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
load more v
23%

A bit of digging into the Elements tab in the devtools revealed the culprit… My React component was rendering in the wrong spot!,The idea here is sound: Our initial compile-time build happens in Node.js, a server runtime. We can detect whether or not we're rendering on the server by checking to see if window exists. If it doesn't, we can abort the render early.,By rendering something different depending on whether we're within the server-side render or not, we're hacking the system. We're rendering one thing on the server, but then telling React to expect something else on the client:

Pretag
 Pretag team - issue, fix, solve, resolve

Other "twice-modal" queries related to "My component in my modal is rerendering twice"