React - Typescript - How to function as prop to another component

Viewed 302

There are three components Toggle, ToggleMenu, Wrapper

The toggle should be universal, and used for different functions The Wrapper should only change background color when toggle is on

The question is how to pass the function that responcible for changing color to togglemenu, that it executs when switch toggle

App

import React from 'react';
import { Wrapper } from './containers/wrapper';
import { Button } from './components/buttons/button';
import { ToggleMenu } from './components/settings/settings';
 
const App = () => {
  return (
    <>
    <Wrapper>
        <Button />
        <ToggleMenu />
    </Wrapper> 
    </>
  )
}

export default App;

ToggleMenu

import styled from "styled-components";
import { Toggle } from "../buttons/toggle";
import { WrapperProps } from "../../containers/wrapper";
import { test } from "./test"

const SettingsContainer = styled.div`
  margin: auto;
  width: 50%;
  height: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: white;
`;

const Container = styled.div`
  height: 50%;
  width: 50%;
  display: flex;
  justify-content: center;
  flex-direction: column;
  background-color: lime;
`;

const TogCon = styled.div`
  margin: 0.5em;
`;

export const ToggleMenu = (props: WrapperProps) => {
  return (
    <SettingsContainer>
      <Container>
        <TogCon>
          <Toggle toggleText={"Dark mode"} onChange={props.handleTheme}/>
        </TogCon>
        <TogCon>
          <Toggle toggleText={"Sth"} onChange={() => {console.log("Sth")}}/>
        </TogCon> 
      </Container>
    </SettingsContainer>
  );
};

Wrapper

import React, { useState } from "react";
import styled from "styled-components";

export type WrapperProps = {
  children?: React.ReactNode;
  color?: string;
  handleTheme?: () => void;
};

const Container = styled.div<WrapperProps>`
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: fixed;
  background-color: ${props => props.color }
`

export const Wrapper = ({ children }: WrapperProps) => {

  const [theme, setTheme] = useState("black")

  const handleTheme = () => {
    theme === "black" ? setTheme("white"): setTheme("black")
  }

  return(
    <Container 
      color={theme}
      handleTheme={handleTheme}
    > { children } 
    </Container>
  );
}
1 Answers

Was solved with React.cloneElement

export const Wrapper = (props: WrapperProps) => {
    
      const [theme, setTheme] = useState("black")
    
      const handleTheme = () => {
        theme === "black" ? setTheme("white"): setTheme("black")
      }
    
      const childrenWithProps = React.Children.map(props.children, child => {
        if (React.isValidElement(child)) {
          return React.cloneElement(child, { handleTheme });
        }
        return child;
      });
    
      return(
        <Container color={theme} > 
          { childrenWithProps }
        </Container>
      );
      }
Related