How to Pass Props to {This.Props.Children}

How to pass props to {this.props.children}

Cloning children with new props

You can use React.Children to iterate over the children, and then clone each element with new props (shallow merged) using React.cloneElement.

See the code comment why I don't recommend this approach.

const Child = ({ childName, sayHello }) => (
<button onClick={() => sayHello(childName)}>{childName}</button>
);

function Parent({ children }) {
// We clone and pass this `sayHello` function
// into the child elements.
function sayHello(childName) {
console.log(`Hello from ${childName} the child`);
}

const childrenWithProps = React.Children.map(children, child => {
// Checking isValidElement is the safe way and avoids a
// typescript error too.
if (React.isValidElement(child)) {
return React.cloneElement(child, { sayHello });
}
return child;
});

return <div>{childrenWithProps}</div>
}

function App() {
// This approach is less type-safe and Typescript friendly since it
// looks like you're trying to render `Child` with `sayHello` missing.
// It's also confusing to readers of this code.
return (
<Parent>
<Child childName="Billy" />
<Child childName="Bob" />
</Parent>
);
}

ReactDOM.render(<App />, document.getElementById("container"));
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="container"></div>

How to pass props to {children} and use it?

You're getting this type error because React.cloneElement() requires an Element to clone; children is not guaranteed to be an element. It's a ReactNode, which is a type alias that includes undefined and null. Those are valid types to return from a React component, but not to pass to cloneElement. You could do this instead:

children = React.Children.map(children, el => {
return React.cloneElement(el, { id: label })
})

This would allow you to clone each element in turn. If you only expect a single element, React.Children.only() can be used in a similar way

children = React.Children.only(children)
children = React.cloneElement(children)

How to pass a prop to {children} in React?

The props.children is a React Element, which is nothing but a plain JS object having the description of what needs to be rendered in the DOM.

To provide additional details, we need to clone the existing React Element object and provide the additional details.

To do this we can use the React.cloneElement API to pass the additional prop to the children :

return (
<section>
{React.cloneElement(children, {didComplete: completeState})}
</section>
);

How to pass data to {props.children}

You can make use of React.cloneElement to React.Children.map to pass on the disabled prop to the immediate children components

const Authorization: React.FC<Props> = (props) => {
const [disabled, setDisabled] = React.useState(false);
const render = (errorMessage : JSX.Element): JSX.Element => {
return (
<>
{<ErrorPanel message={errorMessage} setDisabled={setDisabled}/>}
</>
);
};

return (
<>
<PageLoader
queryResult={apiQuery}
renderPage={render}
/>
{React.Children.map(props.children, child => {
return React.cloneElement(child, { disabled })
})}
</>
);
};

UPDATE:

Since you wish to update the parent state to, you should store the state and parent and update it there itself, instead of storing the state in child component too.

export const Parent: React.FC<Props> = (props) => {
const [disabled, setDisabled] = React.useState(false);
const createContent = (): JSX.Element => {
return (
<Authorization setDisabled={setDisabled}>
{<ErrorPanel message={errorMessage} disabled={disabled} setDisabled={setDisabled}/>}
<MyChildComponent disabled={disabled}/>
</<Authorization>
);
}

return (
<Button onClick={onSubmit} disabled={disabled}>My Button</Button>
{createContent()}
);
};

const Authorization: React.FC<Props> = (props) => {
const render = (errorMessage : JSX.Element): JSX.Element => {
return (
<>
{<ErrorPanel message={errorMessage} disabled={props.disabled} setDisabled={props.setDisabled}/>}
</>
);
};

return (
<>
<PageLoader
queryResult={apiQuery}
renderPage={render}
/>
{props.children}
</>
);
};

How to pass a function as props to React Children?

function Mouse({hovered}) {
return null;
};

function Navbar({toggleHover}) {
return <div onMouseEnter={toggleHover}>Hover on me</div>
};

function Footer({toggleHover}) {
return <div onMouseEnter={toggleHover}>Hover on me</div>
};

function Child({toggleHover}) {
return <div onMouseEnter={toggleHover}>I am child, hover on me</div>
};

function Layout({ preview, children }) {

const [hovered, setHovered] = React.useState(false);

function toggleHover() {
console.log("hovered");
setHovered(!hovered);
}

const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { toggleHover: toggleHover });
}
return child;
});

return (
<div>
<Mouse hovered={hovered} />

<div>
<Navbar toggleHover={toggleHover} />
<main>{childrenWithProps}</main>
<Footer toggleHover={toggleHover} />
</div>
</div>
);
}

function Parent() {
return (
<div>
<Layout>
<Child />
<Child />
<Child />
</Layout>
</div>
)
}

const rootElement = document.getElementById("root");
ReactDOM.render(
<Parent />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

<body>
<div id="root"></div>
</body>


Related Topics



Leave a reply



Submit