Introduction to Props in SolidJS
Okay then my friends, so SolidJS, much like other front-end frameworks, make use of something called props. And props are basically just a way to pass custom properties or values into other components. For example, I might want to pass some custom values into one of these card components so that we can use those values inside the component. And every time we use a card component, we can pass different values into it so they might be different each time around.
And the way we do this is almost identical to how we do it in React. We would just pass in a prop name and we'd set it equal to some kind of value. Now that value could be a string or some other type like a number or a boolean or an object, etc. Now if it's a string, then we can just pass that string as a value in quotes. But if it's a different type, then we need to put the value inside curly braces instead. This is how we output some kind of dynamic value or code in Solid. So if I passed in a number, that would be in curly braces. And the same would be true if I boolean or an object or anything else that's not a string.
For now, what I want to do is pass in a prop into this component called title which is a string. And the value of that could be 'ninja t-shirt'.
Accessing Props and Preserving Reactivity
Now we can accept that prop in the component by just using the props argument inside the component function that we automatically get. Now, if you're coming from React, this is where it's a little bit different because in React, we'd probably just destructure values from the props object, but inside we shouldn't do that because it could break its reactivity. So make sure you don't destructure the props, just keep it as props.
And then we can access the title prop on this props object in the template if we wanted to. So now if we go to the browser, we can see that title right here, the value 'ninja T'. It's not in the other cards because we didn't pass it through. But if we wanted to, we could go back and we could add a title to each one of these, and they could be different each time around. So for example, this could be 'ninja tote bag', and then down here, we could do another title which would be 'ninja hoodie', like so.
So now if we save this, we can see 'ninja tote bag' and 'ninja hoodie'. So this is a way to pass different data into the components.
Using Boolean Props for Conditional Logic
Okay, so that's the title. Now, also what I'd like to do is pass in some options for the card itself. For example, we have all these different styles right here. Now, what I'd like to do is maybe have some props in these cards whereby we could say do we want a shadow or do we want round corners or something like that. So that's what we're going to do now. And what I'll do is I'll just comment out one of them because we only need two for this. So we'll keep the titles, but also I want a couple more props.
So those two props are going to be rounded and we're going to set that equal to true, and then also flat and we're going to set that equal to false. So this rounded one is going to be whether we want the card to have rounded corners, the border radius if you like, and this one right here is telling us whether we want the card to be flat or not, and that refers to the box shadow. So in this case, we do want rounded corners because this is true, and we don't want it to be flat, so we do want that box shadow.
And we're going to do something similar for this card down here, but we'll have different values. So rounded is going to be false and flat is going to be true. Okay then, so let me save this.
Dynamic Classes with the classList Property
Now we need to use these different props over here in the card. And remember, they're attached to this props object. Now the way we're going to work with this is by using some conditional classes because we want to conditionally output classes on this div dependent on the values of those props. And the way we do that in Solid is by using the classList attribute, or rather property. So we can say classList and we set that equal to something dynamic, and in fact, it's an object.
And the way this works is we have properties and values. Now the properties are the class names we want to conditionally apply to it and the values of those are true or false. If the value is true, we apply that class, if the value is false, we don't. So the classes or the property names we want here are going to be rounded-md and that's for this one right here, rounded, and also shadow-md... I think that should be shadow-md all right, not ms. So shadow-md, and that's for this prop right here, flat.
So then we'll say in quotes rounded-md, and the value of that is going to be props.rounded and that's going to be true or false, this thing right here. Yeah. And then the next one is going to be shadow-md, and that's going to be !props.flat. And it's exclamation because it's the opposite of this, right? So if flat is false, then we do want the class, so we reverse it. Okay, and now we can take them off here because we don't want to apply them to every card, only to cards based on these prop values.
All right, so let's give this a whirl. We should see that the first card is rounded and also has the shadow. The second one shouldn't be rounded and shouldn't have the shadow. So let's check it out. All right, yeah, rounded at the corners with a shadow, not rounded, and doesn't have a shadow. Awesome. Okay, cool.
The Case for props.children
So now we've seen how we can pass these props into components, but using props like this does have its limitations. For example, what if I wanted to have lots of different content inside each of these cards? So not just a different title, but also maybe a different paragraph of text, maybe a different image, even a totally different template. Well then, props wouldn't really be able to efficiently solve that because we don't want to be making props for loads of different content, templates, images, all that kind of jazz. That would get really messy, right?
But what we can do is pass in custom content and templates using the children property on the props object. So let me show you how that works. So I'm first going to get rid of the title prop in each of these components, we don't need that anymore, and you'll see why in a second. And if we go to the component, we can take out the props.title as well, we don't need that. And in fact, I'm going to cut all of this. So now we just have a div with no content inside the div, just a div with classes.
Implementing props.children for Custom Templates
Now if we go back to app.jsx, what I'd like to do is make this so now it's no longer self-closing, so we have the closing tag as well. And now I want to make it so we can pass a custom template and custom content into this card by nesting it inside these tags. So I could paste in this content right here, and I could put in a title, for example, 'Ninja t-shirt, black', like so. Now let me just scoot that in.
I'm going to copy that again. I'm going to do the same thing down here. Your closing tag, and then inside that I'm going to output this template again. We'll change the title and that's going to be 'ninja T', and we'll do 'white' for this. We'll change the order of the content as well. So let's grab that button and let's put it up here instead. And maybe we'll put a price at the bottom, so 'only 10 pounds' or something like that. And we'll change the button text to 'View', we'll do that on both.
So now we have different content going into each of these cards, and we want to output that content inside this div right here. And the way we do that is just by using curly braces because we're outputting something dynamic and then saying props.children. And this children property on the props represents whatever children we pass into the card. And these are all the children right here, the children elements if you like.
So it takes all of this content and it outputs it right here where we output props.children. And now we should see that content, this and this, inside the cards. So let's take a look. And we do. Awesome. So that's a nice way to pass custom templates and content into other components.