Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

142
Views
How to change child state from another child without re-rendering parent

I want to change the content of a child component in response to a user event in another child component without causing the parent to re-render.

I've tried storing the child state setter to a variable in the parent but it is not defined by the time the children have all rendered, so it doesn't work.

Is there a minimal way to accomplish this (without installing a state management library)?

ChildToChild.tsx

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

export default function ChildToChild() {
  const renderCounter = useRef(0);
  renderCounter.current = renderCounter.current + 1;

  let setChildOneContent;
  const childOneContentController = (
    setter: Dispatch<SetStateAction<string>>
  ) => {
    setChildOneContent = setter;
  };

  return (
    <div>
      <h1>Don't re-render me please</h1>
      <p>No. Renders: {renderCounter.current}</p>
      <ChildOne childOneContentController={childOneContentController} />
      <ChildTwo setChildOneContent={setChildOneContent} />
    </div>
  );
}

function ChildOne({
  childOneContentController,
}: {
  childOneContentController: (setter: Dispatch<SetStateAction<string>>) => void;
}) {
  const [content, setContent] = useState("original content");

  useEffect(() => {
    childOneContentController(setContent);
  }, [childOneContentController, setContent]);

  return (
    <div>
      <h2>Child One</h2>
      <p>{content}</p>
    </div>
  );
}

function ChildTwo({
  setChildOneContent,
}: {
  setChildOneContent: Dispatch<SetStateAction<string>> | undefined;
}) {
  return (
    <div>
      <h2>Child Two</h2>
      <button
        onClick={() => {
          if (setChildOneContent) setChildOneContent("content changed");
        }}
      >
        Change Child One Content
      </button>
    </div>
  );
}
about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

You should be able to achieve by

  1. Using state in child components
  2. Using a callback function in the parent component that calls the setState function of the child component. This will trigger re-render of the child but not of itself (parent).

Demo: https://codesandbox.io/s/child-re-rendering-only-x37ol

about 4 years ago · Juan Pablo Isaza Report

0

For an one-off, you could use the following (another ref to store & use the ChildOne setContent:

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

function ChildOne({
  setChildOneRef
}: {
  setChildOneRef: React.MutableRefObject<React.Dispatch<
    React.SetStateAction<string>
  > | null>;
}) {
  const [content, setContent] = useState("original content");

  useEffect(() => {
    setChildOneRef.current = setContent;
  }, [setChildOneRef]);

  return (
    <div>
      <h2>Child One</h2>
      <p>{content}</p>
    </div>
  );
}

function ChildTwo({
  setChildOneRef
}: {
  setChildOneRef: React.MutableRefObject<React.Dispatch<
    React.SetStateAction<string>
  > | null>;
}) {
  return (
    <div>
      <h2>Child Two</h2>
      <button
        onClick={() => {
          setChildOneRef.current?.("content changed");
        }}
      >
        Change Child One Content
      </button>
    </div>
  );
}

export function ChildToChild() {
  const renderCounter = useRef(0);
  renderCounter.current = renderCounter.current + 1;

  const setChildOneRef = useRef<Dispatch<SetStateAction<string>> | null>(null);
  return (
    <div>
      <h1>Don't re-render me please</h1>
      <p>No. Renders: {renderCounter.current}</p>
      <ChildOne setChildOneRef={setChildOneRef} />
      <ChildTwo setChildOneRef={setChildOneRef} />
    </div>
  );
}

If this pattern is common in your code, you may still want to use state management library or evaluate if "childs" should be really separated.

about 4 years ago · Juan Pablo Isaza Report

0

You can create an object, store the hook on that object, and use the hook from the object on the children. Not sure why the output count increments twice...

import { useState } from "react";

let parentRenderCount = 0;
let child1RenderCount = 0;
let child2RenderCount = 0;

const Child1 = ( { stateHolder } ) => {
    const [count, setCount] = useState( 0 )
    console.log('child1 render', ++child1RenderCount)
    stateHolder.count = count
    stateHolder.setCount = setCount
    return <div>
        {count}
    </div>
}

const Child2 = ( { stateHolder } ) => {
    console.log('child2 render', ++child2RenderCount)
    return <button onClick={() => stateHolder.setCount( stateHolder.count + 1 )}>
        clickme
    </button>
}


function App() {
    const stateHolder = { }
    console.log('parent render', ++parentRenderCount)
    return (
        <div className="App">
            <Child1 stateHolder={stateHolder} />
            <Child2 stateHolder={stateHolder} />
        </div>
    );
}

export default App;
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!