How to return variables from a component using function as a child component?

Viewed 147

I hope someone can shed light on this. Using the react Route component gave me this idea and I can't figure it out

The React <Route> component seems to render the children, but it also returns variables such as match. Here's an example of what I'm talking about:

<Route exact path="/">
  {({ match }) => (
    <div>
      {`${JSON.stringify(match)}`}
    </div>
  )}
</Route>

Notice that even though match was not declared anywhere in the component, the variable is returned by Route so that it can be accessed in the children.

If I wanted to do this in one of my own components, how would this be accomplished?

I tried this:

const Test = (props: any): any => {
  return {
    testVariable: "test variable",
    render: (
      <>
        {props.children}
      </>
    ) 
  };
};

And would expect to be able to use it like this:

<Test>
  {({ testVariable }) => (
    <p>{testVariable}</p>
  )}
</Test>

But it now works as my expectation.

EDIT: This has been solved, thanks to novonimo's answer below. I learned that the technical term for this functionality is called Function as a Child Component (FaCC).

Here's a useful tutorial that I was able to find after reading novonimo's answer.

1 Answers

It's very interesting and sometimes wired to facing.

I'll take a counter example to show you how you could do that:

import React, {useEffect, useState} from "react";


const ChildComponent = ({children}) => {
  const [counter, setCounter] = useState(0)

  useEffect(() => {
    setInterval(() => {
      setCounter(prevState => prevState + 1)
    }, 1000)
  }, [])

  return children(new Date(), counter)
}

const ParentComponent = () => (
    <ChildComponent>
      {(startedAt, currentNumber) => (<p>started at: {startedAt} and current number is : {currentNumber}</p>)}
    </ChildComponent>
);

export default ParentComponent

try it on CodeSandbox

Explanation:

There are two components, child and parent.

In the ChildComponent, a simple counter where implemented. it changes every 1000 milliseconds.

children is a standard property name for passing children to a component.

In the ParentComponenet, a function (() => {}) passed as a children to the ChildComponent, it's the key of solution,

So far, we passed a function as children into the ChildComponent. with every change on countner variable, the ChildComponent will re-render, and every time the children(new Date(), counter) will be called.

the children function is now called in every 1 second and causes re-rendering on ChildComponent. so in the ParentComponent the arrow function (which passed as children with two arguments) will invoke every 1 second.

Related