Instructor: In our usage example here, we want to have complete and entire control over the rendering. We want to be able to render a div. We want to be able to render a switch and a custom button. Right now, with the way that our toggle is implemented, it only renders a switch and it has complete control over rendering.
We're going to iterate to support this API. We'll start by taking this and creating a new function called renderUI. Then we'll simply replace render with return this.renderUI. Next, we'll turn renderUI into a pure function, so it accepts on and toggle in an object.
Instead of referencing this.toggle, it just passes toggle. Then we pass those things to a renderUI function on it's this.state.on and toggle is this.toggle. Everything's still working as it was before. Now, because this is a pure function, it doesn't actually need to exist on the instance.
It's not using any instance method or properties so we can pull this off, make it an error function and then remove this dot so that it references the error function we have to find up here. That's still working.
Next, let's go ahead and make a static default props here, and we'll accept a prop called renderUI, and we'll make the default of renderUI be this function. Then we can return this.props.renderUI, and now users of our component could use that API. S
We'll pull this out, we'll say renderUI equals at error function and we get exactly what we were looking for. Now we have total and complete control over rendering of this component. We get all the information that we need, the state and any event handlers to change that state, and then we can return the JSX that we want to have rendered for this component.
Now, our use case doesn't really make sense to provide a default implementation for renderUI, so we'll get rid of that default prop, and also it's more common to call this renderUI prop children. That all still works, and because it's called children, we can actually have the API we were looking for in the first place. Everything works great.
We iterated to this solution, but it's actually quite simple. To support a render prop API, you simply remove all the contents of the render method and return this.props.children and call that as a function. You provide any state and state updaters or helper functions that your consumers need so they can be responsible for rendering.
This gives people ultimate flexibility over how your component is rendered, and this is the render prop API. It's the most primitive form of UI flexibility, and any other pattern can be implemented on top of this API.
One of the really nice things about this API is you can actually implement the previous API that we had with the new API. If you have a common use case, we can say function common toggle. That'll accept some props. Then you can return toggle, spread those props, and then you can provide your own children function that renders the common UI.
In our case, we could provide switch on is on and on click is toggle. And then we'll de-structure the state and the helpers. And now people can use the common toggle which is limited in flexibility but has a simpler API, and it's all built on top of the render prop API that toggle exposes.