[Proposal] Add component properties like children

This issue has been created since 2022-11-18.

I propose to add support to custom child properties. This expand the options to create and organize the components and can reduce the amount of components in some cases.

Current Behavior

const MyComponent = (props) => {
  const { header, body, footer } = props
  return (
    <div>
      <div>{header}</div>
      <div>{body}</div>
      <div>{footer}</div>
    </div>
  )
}

const Page = () =>
  <MyComponent
    header={
      <div>
        <Brand>My Brand</Brand>
        <Menu>
          <MenuItem>Item 1</MenuItem>
          <MenuItem>Item 2</MenuItem>
          <MenuItem>Item 3</MenuItem>
          <MenuItem>Item 4</MenuItem>
        </Menu>
        <UserName>Codeco</UserName>
        <SignOutButton />
      <div>
    }
    body={
      <div>
        <p>My content 1</p>
        <p>My content 2</p>
        <p>My content 3</p>
        <p>My content 4</p>
        <p>My content 5</p>
        <p>My content 6</p>
        <p>My content 7</p>
        <p>My content 8</p>
        <p>My content 9</p>
      </div>
    }
    footer={
      <div>
        <b>codeco</b>
        <b>proposal</b>
        <b>2022</b>
      </div>
    }
  />

Desired Behavior

const MyComponent = (props) => {
  const { header, body, footer } = props
  return (
    <div>
      <div>{header}</div>
      <div>{body}</div>
      <div>{footer}</div>
    </div>
  )
}

const Page = () =>
  <MyComponent>
    <MyComponent.header>
      <div>
        <Brand>My Brand</Brand>
        <Menu>
          <MenuItem>Item 1</MenuItem>
          <MenuItem>Item 2</MenuItem>
          <MenuItem>Item 3</MenuItem>
          <MenuItem>Item 4</MenuItem>
        </Menu>
        <UserName>Codeco</UserName>
        <SignOutButton />
      <div>
    </MyComponent.header>
    <MyComponent.body>
      <div>
        <p>My content 1</p>
        <p>My content 2</p>
        <p>My content 3</p>
        <p>My content 4</p>
        <p>My content 5</p>
        <p>My content 6</p>
        <p>My content 7</p>
        <p>My content 8</p>
        <p>My content 9</p>
      </div>
    </MyComponent.body>
    <MyComponent.footer>
      <div>
        <b>codeco</b>
        <b>proposal</b>
        <b>2022</b>
      </div>
    </MyComponent.footer>
  </MyComponent>

This example above expand the options to create and organize the components.

To use a real case...

Some developers make their codes like this:

<Card variant="outlined">
  <CardContent>
    <Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
      Word of the Day
    </Typography>
    <Typography variant="h5" component="div">
      be{bull}nev{bull}o{bull}lent
    </Typography>
    <Typography sx={{ mb: 1.5 }} color="text.secondary">
      adjective
    </Typography>
    <Typography variant="body2">
      well meaning and kindly.
      <br />
      {'"a benevolent smile"'}
    </Typography>
  </CardContent>
  <CardActions>
    <Button size="small">Learn More</Button>
  </CardActions>
</Card>

... creating two components (CardContent and CardActions) to direct the content...

(this example was copied from https://mui.com/pt/material-ui/react-card/#OutlinedCard.tsx and changed to simplify)

... but imagine doing something like this:

<Card variant="outlined">
  <Card.Content>
    <Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
      Word of the Day
    </Typography>
    <Typography variant="h5" component="div">
      be{bull}nev{bull}o{bull}lent
    </Typography>
    <Typography sx={{ mb: 1.5 }} color="text.secondary">
      adjective
    </Typography>
    <Typography variant="body2">
      well meaning and kindly.
      <br />
      {'"a benevolent smile"'}
    </Typography>
  </Card.Content>
  <Card.Actions>
    <Button size="small">Learn More</Button>
  </Card.Actions>
</Card>

eliminating the need to create more components, reducing the amount of components on the page.

So, adding support to use the components properties, like header; body and footer from MyComponent in my example, as a children make possible this behaviors.

make sense?

zJaaal wrote this answer on 2022-11-30

You can actually do this using Compound Components Design Pattern. There you have an small guide of how to implement it.

That's one way to do it.

You can use the Children to manipulate the children in your component and the cloneElement to change the props on every child

Here is an example of an If/Else component (this pattern is not a good approach of how to do this. Is just for educational purposes):

import { Children, cloneElement } from "react";

const If = ({ children, predicate }) => {
  return Children.map(children, (child) => {
    return cloneElement(child, { predicate });
  });
};

const Then = ({ children, predicate }) => {
  return predicate ? <>{children}</> : <></>;
};

const Else = ({ children, predicate }) => {
  return !predicate ? <>{children}</> : <></>;
};

If.then = Then;
If.else = Else;

export default If;

Look how I created two properties on the main component and assigned the proper component to it, so now you can just do something like:

import If from "./components/If";
import { useState } from "react";

function App() {
  const [random, setRandom] = useState(Math.random() * 100);
  return (
    <div
      style={{ display: "flex", height: "inherit", flexDirection: "column" }}
    >
      <If predicate={random <= 50}>
        <If.then>
          <p style={{ color: random < 40 ? "blue" : "red" }}>I'm {random}</p>
        </If.then>
        <If.else>
          <div>
            <p style={{ color: random > 80 ? "green" : "violet" }}>
              I'm {random}
            </p>
            <button onClick={() => setRandom(0)}>Reset</button>
          </div>
        </If.else>
      </If>
      <button
        onClick={() => setRandom(Math.random() * 100)}
        style={{ width: "50%" }}
      >
        Randomize
      </button>
    </div>
  );
}

export default App;

In that snippet I made the implementation where I just generate random numbers and if is equal or less than 50 I just render "I'm 34" (In case that random is 34). In other ways I render the same message but with a button to reset the random number to 0.

I actually have this code with more components like Switch or a Counter using Compound Components Pattern in a public repository. I'll drop it right here

Hope you find this helpful.

Kindest Regards,

zJaaal

More Details About Repo
Owner Name facebook
Repo Name react
Full Name facebook/react
Language JavaScript
Created Date 2013-05-24
Updated Date 2022-12-10
Star Count 198882
Watcher Count 6638
Fork Count 41302
Issue Count 1120

YOU MAY BE INTERESTED

Issue Title Created Date Comment Count Updated Date
Poetry Refuses to add blacken-docs 0 2022-01-06 2022-12-02
Allow bulk conversion to safe PDFs 10 2020-04-23 2022-10-17
WordPress's partial match redirect tries to redirect to Popup Maker custom post types which throws a 404 2 2022-07-06 2022-08-01
Prometheus operator support in the Helm Chart 1 2021-06-17 2022-12-04
Cannot open on MacBook Pro 13 2018 9 2021-12-29 2022-12-03
[Discussion] Safe to upgrade to Big Sur? 12 2021-01-10 2022-10-08
log warning when adding @web decorator whitout webapp: true in maubot.yaml 0 2019-09-04 2022-11-22
some problem with pyglet 0 2021-12-07 2022-12-03
Killing the Xtightvnc process manually 4 2020-08-30 2022-10-23
How to do the inference with the TST (Transformer) ? 5 2021-07-13 2022-07-10
Unable to get applyPolyfills && defineCustomElements to import / work properly 6 2021-02-16 2022-11-24
5.9.9.99的一个问题 0 2021-08-29 2022-01-17
Message reminders 7 2021-08-31 2021-12-10
Extra Spaces Between Markers in Bar Plot 6 2022-08-29 2022-11-10
win10更新后出现菜单栏和标题栏 2 2021-09-23 2022-01-14
mac 1.16.11 arm 版本 打开崩溃 1 2021-09-24 2022-11-19
通过 FairBinding packages 生成的文件应该自动导入对应引用 0 2022-09-13 2022-11-07
ios failed to call plugin method: FairJSBridge.m exceptionValue:TypeError: undefined is not an object (evaluating 'mClass[funcName]') 0 2022-10-10 2022-11-07
Unable to connect to a specified MySQL host from AWS ECS 1 2021-06-01 2022-10-09
Network and Caddy has complex problems 2 2022-11-07 2022-12-02
Authentication fails with "User gesture is not detected" 2 2022-06-10 2022-12-03
接收器 (receiver) 与接口 这一节有问题 5 2020-12-22 2022-11-22
Not working at Mac OS Big Sur 1 2020-12-18 2022-11-02
Call for testing: ZLint v3.1.0 release candidate 1 2021-01-30 2022-11-29
Appium output log to file get stuck 2 2022-05-06 2022-11-10
[BUG] `go-git/v5/utils/diff` producing wrong results 2 2021-07-06 2022-11-30
Keyboard is reported twice in monitor, same VID/PID, but different handle 0 2021-01-18 2022-11-18
Unable to run the Demo 1 2021-04-15 2022-10-28
Let folks stop the filmstrip at LCP 0 2021-12-10 2022-11-17
port: Fix test SendDirectLineMessage() (#6014) 0 2021-12-07 2022-12-06
Send message to websocket 2 2021-10-11 2022-09-25
IF condition dont go forward to next node 3 2021-12-29 2022-11-06
Error thrown when creating a backup 11 2021-08-01 2022-08-22
[Feature Request] Local URL Username and Password Fields 1 2020-04-23 2022-11-18
chore: references to "googleapis" master branch 1 2021-09-03 2022-11-21
Broken tests in Julia 1.6.0-beta1 5 2021-01-09 2022-11-21
Taylor1 all zero for function that includes negative integer powers 4 2021-04-08 2022-11-21
请问一下uniapp支持android窗口小工具与ios 的widget 吗 2 2021-09-27 2022-11-05
Download Zip button issue. 4 2020-10-16 2022-11-12
[BUG] PeekMessages/PeekMessage not receiving all messages after new ones were added to topic. 1 2022-11-16 2022-11-22
macOS extension to share files from finder crash /impossible to share files to telegram 0 2021-12-17 2022-11-13
Winget tells me that Windows Terminal needs an update, but the Windows Store says no update is available 7 2021-09-02 2022-12-09
关于marketface表情 1 2021-11-19 2022-01-20
How to change the color of landmarks in pose tracking for android (pose_tracking_gpu) 4 2022-09-19 2022-10-24
Support spec.externalIPs and NodePort services 8 2021-03-20 2022-11-12
How to set the legend area into two-columns in Apache Echarts 1 2022-05-16 2022-12-08
add Description and validation properties to EnvVar in the REST API so that environment variables can have better tooling 8 2015-02-06 2022-11-24
Documentation: Example of Apache Reverse Proxy config does not work with 2.4+ 1 2020-11-11 2022-12-04
[StopWatch] StopwatchEvent::getDuration() always returns 0 0 2022-08-01 2022-08-21
UserModel添加GetUserById()方法 0 2016-11-23 2022-12-03