Home > Software design >  In how many ways we can pass props to all child components in react
In how many ways we can pass props to all child components in react

Time:10-24

I have an app code

import React from "react";
import { Route, Switch } from "react-router-dom";
import Minidrawer from './components/Drawer/Minidrawer'
import { makeStyles } from '@mui/styles';
import Box from '@mui/material/Box';
import Main from "./components/Main/Main";
import {useSelector} from 'react-redux'


const useStyles = makeStyles({
  container: {
    display: "flex"
  }
});

export default function App() {
  const classes = useStyles();
  const user = useSelector((state) => state.auth);

  return (
    <Box sx={{ display: 'flex' }}>
      <Minidrawer currUser={user}/>
      <Switch>
        <Route exact from="/" render={props => <Main childText="home" currUser={user} {...props} />} />
        <Route exact path="/auth" render={props => <Main childText="auth" currUser={user} {...props} />} />
        <Route exact path="/register-client" render={props => <Main childText="registerClient" currUser={user} {...props} />} />
      </Switch>
      </Box>
  );
}

I have to pass currUser to all child components imported in App but I do not want to duplicate the code, what are different ways to achieve this so that all of the components have access to currUser?

CodePudding user response:

if I understand what you want to do, you want to pass props to all children of a component, if the components are simple components you can do as follows:

import React from "react";
import Main from "./Main";
import PassPropsToNormalComponents from "./PassPropsToNormalComponents";

export default function App() {
  const user = {
    username: "lakhdar"
  };

  return (
    <div style={{ display: "flex" }}>
      <PassPropsToNormalComponents currUser={user}>
        <Main childText="home" />
        <Main childText="auth" />
        <Main childText="registerClient" />
      </PassPropsToNormalComponents>
    </div>
  );

and this is the PassPropsToNormalComponents file

import React from "react";

export default function PassPropsToNormalComponents({ children, ...props }) {
  const childrenWithProps = React.Children.map(children, (child) => {
    if (React.isValidElement(child)) {
      return React.cloneElement(child, { ...child.props, ...props });
    }
    return child;
  });

  return <>{childrenWithProps}</>;
}

but in your case passing the props to the routes wont' make the routes pass the props to their rendered components so we need an extra step here:

first the file where we provide the props to the parent:

import React from "react";
import { Route, Switch } from "react-router-dom";
import Main from "./Main";
import PassPropsToRouteComponents from "./PassPropsToRouteComponents";

export default function App() {
  const user = {
    username: "lakhdar"
  };

  return (
    <div style={{ display: "flex" }}>
      <Switch>
        <PassPropsToRouteComponents currUser={user}>
          <Route
            exact
            from="/"
            render={(props) => {
              return <Main childText="home" {...props} />;
            }}
          />
          <Route
            exact
            path="/auth"
            render={(props) => <Main childText="auth" {...props} />}
          />
          <Route
            exact
            path="/register-client"
            render={(props) => <Main childText="registerClient" {...props} />}
          />
        </PassPropsToRouteComponents>
      </Switch>
    </div>
  );
}

and finally, the extra step is to get the rendered element and pass it its own props the props from the parent, and the file looks like this:

import React from "react";

export default function PassPropsToRouteComponents({ children, ...props }) {
  const childrenWithProps = React.Children.map(children, (child) => {
    if (React.isValidElement(child)) {
      const routerChild = child.props.render();
      return React.cloneElement(child, {
        ...child.props,
        render: () => {
          return React.cloneElement(routerChild, {
            ...routerChild.props,
            ...props
          });
        }
      });
    }
    return child;
  });

  return <>{childrenWithProps}</>;
}

link to working codesandbox: https://codesandbox.io/s/gracious-meadow-dj53s

I hope this is what you've been looking for.

CodePudding user response:

You could use redux or the context API.

Redux: https://react-redux.js.org/

Context API: https://reactjs.org/docs/context.html

  • Related