Search code examples
javascriptreactjsreact-hooksstyled-components

Passing React State Between Imported Components


I am trying to pass state from parent to child using React, however both components are imported and therefor the state variables of the parent component are not declared.

I have two components both exported from the same file. The first component is a wrapper for the second. This component has a useEffect function which find its height and width and set these values to hook state.

export const TooltipWrapper = ({ children, ariaLabel, ...props }) => {
  const [width, setWidth] = React.useState(0);
  const [height, setHeight] = React.useState(0);
  const ref = React.useRef(null);
     React.useEffect(() => {
       if (ref.current && ref.current.getBoundingClientRect().width) {
         setWidth(ref.current.getBoundingClientRect().width);
       }
       if (ref.current && ref.current.getBoundingClientRect().height) {
         setHeight(ref.current.getBoundingClientRect().height);
       }
     });
  return <TooltipDiv>{children}</TooltipDiv>;

The next component which is exported from the same file looks like this

export const Tooltip = ({
  ariaLabel,
  icon,
  iconDescription,
  text,
  modifiers,
  wrapperWidth,
}) => {
  return (
    <TooltipContainer
      aria-label={ariaLabel}
      width={wrapperWidth}
    >
      <TooltipArrow data-testid="tooltip-arrow" modifiers={modifiers} />
      <TooltipLabel
        aria-label={ariaLabel}
      >
        {text}
      </TooltipLabel>
    </TooltipContainer>
  );
};

The component Tooltip is expecting a prop wrapperWidth. This is where I want to pass in the width hook value from the TooltipWrapper component.

Both components are imported into my App component

import React from "react";
import { GlobalStyle } from "./pattern-library/utils";
import { Tooltip, TooltipWrapper } from "./pattern-library/components/";


function App() {
  return (
    <div className="App">
      <div style={{ padding: "2rem", position: "relative" }}>
        <TooltipWrapper>
          <button style={{ position: "relative" }}>click </button>
          <Tooltip
            modifiers={["right"]}
            text="changing width"
            wrapperWidth={width}
          />
        </TooltipWrapper>
      </div>
    </div>
  );
}

Here I am told that width is not defined, which I expect since I'm not declaring width in this file.

Does anyone have an idea of how I can access the width and height state value for the parent component within the App file?


Solution

  • Render Props could work:

    Add a renderTooltip prop to <TooltipWrapper>:

    <TooltipWrapper renderTooltip={({ width }) => <Tooltip ...existing wrapperWidth={width} />}>
      <button style={{ position: 'relative' }}>click</button>
    </TooltipWrapper>
    

    NB. ...existing is just the other props you are using with Tooltip

    And then update the return of <TooltipWrapper>:

    return (
      <TooltipDiv>
        {children}
        props.renderTooltip({ width }); 
      </TooltipDiv>
    );