Compound component gives more rendering control to the user. The functionality of the component stays intact while how it looks and the order of the children can be changed at will. We get this functionality by using the special React.Children.map
function to map over the children given to our <Toggle/>
component. We map over the children to pass the on
state as a prop to its children. We move the visual pieces of the component out into function components and add them as static properties to <Toggle/>
.
A Community Resource means that itβs free to access for all. The instructor of this lesson requested it to be open to the public.
Why we need clone children? Can we pass just this.props.children
instead of cloning elements?
Give it a try π
You'll find that the components you render don't have the necessary props. We need to pass the props somehow, but we only have access to those props from within our toggle component. So our toggle component is responsible for passing those props in a way that implicit to users.
I don't understand why you are passing the arguments of a function as an object, like in:
function toggleOn({on, children}) { ... }
Thats just destructing the props.
same as
function toggleOn(props) {
const {on, children} = props
...
}
`
Is it a good practice to pass 'toggle' method to all the children, since we use this method with one of them only? Or it's done just on a demonstration purpose?
Hi Pavel. The thing is that there's no reasonable way to know which child needs it and which doesn't. I mean, you could look at the type property of the child and that would allow you to know, but someone could make a custom component that expects to get the prop as well. No harm passing it to all of them π
What is the purpose of adding
static On = ToggleOn
static Off = ToggleOff
static Button = ToggleButton
to the Toggle component? Where are these properties referenced?
Hi Kent, What about adding a component that is neither a Toggle.On, Toggle.Off, or Toggle.Button? Should there be some sort of error checking? When I think of compound components, I think of HTML's select and option tags. You can't add a div inside a select tag. Also, an option tag cannot be outside of a select tag. Is there ways to control that?
Sure! You could definitely add validation. See here: https://codesandbox.io/s/v835q7o193
You'll see I added an array of the valid types and then I check child.type
against that array and log an error if the child's type is invalid. :)
Thank you so much Kent! That was awesome for you taking the time to create a code sandbox example! Loving the tutorial!
Can we use a Context API instead of cloning-and-assigning props? This will allow to pick values at any level of the tree. For example, if user adds containers as first level, and places Toggle.On inside these containers. Edit: Ahh... Its in the next lesson. Sorry...
To follow up on Artyom's comment: I don't understand why we need to clone the children either. It works fine without:
https://codesandbox.io/s/y2p7or1509
I'm afraid that doesn't work. When you do: <Toggle.On />
that creates a react element which is an object, which is why you get this error in that codesandbox:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
argh, ignore me, I hadn't saved the editor, that's why it was still working πππ
I was trying to follow everything you did here in my environment which is using create-react-app. but I just don't understand how the Switch cab be looked like that. When I'd pasted your Switch code and CSS you provide, it just a checkbox and empty value button. am I missing something?
Hi Edwin maybe you can try to download the codesanbox that Kent created and compare it with yours: https://codesandbox.io/s/v835q7o193
I downloaded, installed the dependencies and run it and it looks great.
Very cool, Iβm digging the the new api