JSX syntax arrow function inside render - javascript

I just saw this code in this other question and i don't understand how it works :
let Parent = () => (
<ApiSubscribe>
{api => <Child api={api} />}
</ApiSubscribe>
)
I understand something like this:
let Parent = ({api}) => (
<ApiSubscribe>
<Child api={api} />
</ApiSubscribe>
)
but never saw {foo => <Bar bar={bar} />} in render before,
can someone help me understand this?

A component can access the child elements given to it with the children prop. If a function is given as child, the component can call this function. The component calling the children function can then call the function with any argument it sees fit.
Example
const Child = props => {
return props.children('test');
};
const Parent = () => (
<Child>
{function(arg1) {
return <div> This is a {arg1} </div>;
}}
</Child>
);
ReactDOM.render(<Parent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Related

How to mount child component outside parent using React?

I know that there is React portals that may solves the problem, but portals mount child components outside of DOM tree if I understand it correctly. But I need to render child component inside DOM tree but just outside the parent. Here the example.
I have a page:
const Page = () => {
return (
<>
// -> the place to mount <Child_2/> <--
<Parent/>
</>)
I have the Parent:
const Parent = () => {
return (
<>
<Child_1/>
<Child_2/> //<- I need it NOT to mount here but outside the parent
// in the <Page> component and not outside the DOM.
</>
)
How can I do it? And yet can I make it by portal?
In React doc I found an example just for case:
<html>
<body>
<div id="app-root"></div>
<div id="modal-root"></div>
</body>
</html>
But it is not my case...
const Page = ()=> {
const [el, setEl] = React.useState(null);
return (
<>
<div ref={setEl}></div>
{el && <Parent el={el} />}
</>
)
}
const Parent = ({el})=> {
React.useEffect();
return (
<>
<Child_1/>
{ReactDOM.createPortal(<Child2 />,el)}
</>
)
}

Is there a way to pass data to props.children in a functional component

I am working a project and want to be able to send data from a component to its props.children component. I think this is done using render props in class components but I don't know how to implement it in a functional one. Here is an extremely simplified version of something I am trying to accomplish. I want to render different things in the Child component depending on what "edit" is set to in Parent.
function Parent({ children }) {
const [edit, setEdit] = useState(false);
return (
<div>
{"blah blah blah..."}
<button onClick={()=>{setEdit(!edit)}}>Click</button>
{children}
</div>
);
}
function Child() {
if (edit === true) {
return (
<Parent>
{"Edit is True"}
</Parent>
);
}
return (
<Parent>
{"Edit is False"}
</Parent>
);
}
You have to generate children components by cloning elements manually.
How to pass props to {this.props.children}
Is this what you need? You can share states to children
const Parent = () => {
const [edit, setEdit] = useState(true);
return (
<>
<div>Hello</div>
<Child edit={edit} />
</>
);
};
const Child = params => {
return params.edit? (
<div>Do something if true</div>
):
(
<div>Do something if false</div>
)
};

Adding a click handler to React children for methods on the child component

I understand passing a method down as a prop from a parent to child component. For some reason I'm having a hard time wrapping my head around accessing a child components methods from props.children.
Hopefully my pseudo-code will make sense.
// ParentComponent
...
<ChildComponent>
<button onClick={myMethod}></button>
</ChildComponent>
...
// ChildComponent
...
myMethod() {
dosomething...
}
render() {
return (
<div>
{this.props.children}
</div>
)
}
...
So in this example, I want to access 'myMethod' from a button that I pass to React children. In my real world problem, the button was originally in the render method of childComponent, but I wanted more flexibility. I think it can be done with refs, but I dont think thats the best way to do it, or if what I'm doing is even the right way to go about it. Much thanks!
There isn't any good way of doing this. You can use something like this. But, if you pass more than one child here, all of them will respond to this click handler! So, you should think of another logic to use this Button. As in this state, your ChildrenComponent is so generic.
So, what will your Button component do? You can create a component with this click handler and all other parts can be passed as props. Maybe in this way you can use it in multiple places.
const App = () => (
<div>
<ChildComponent>
<button>Click</button>
</ChildComponent>
</div>
);
const ChildComponent = ( props ) => {
const handleClick = () => console.log( "clicked" );
return (
<div>
{ React.cloneElement( props.children, { onClick: handleClick } ) }
</div>
);
};
ReactDOM.render(
<App />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
function Child(props, ref) {
useImperativeHandle(ref, () => ({
onClick: () => {
//Do something
}
}));
return <div>child</div>;
}
Child = forwardRef(Child);
function Parent(props) {
ChildRef = useRef()
//here you can call it fom parent
ChildRef.current.focus()
return (
<Child ref={ChildRef} />
)
}

React/ES6: curly braces in function signature? [duplicate]

I know you can pass all a react components props to it's child component like this:
const ParentComponent = () => (
<div>
<h1>Parent Component</h1>
<ChildComponent {...this.props} />
</div>
)
But how do you then retrieve those props if the child component is stateless? I know if it is a class component you can just access them as this.prop.whatever, but what do you pass as the argument into the stateless component?
const ChildComponent = ({ *what goes here?* }) => (
<div>
<h1>Child Component</h1>
</div>
)
When you write
const ChildComponent = ({ someProp }) => (
<div>
<h1>Child Component {someProp}</h1>
</div>
)
From all the props that you are passing to the childComponent you are just destructuring to get only someProp. If the number of props that you want to use in ChildComponents are countable(few) amongst the total number of props that are available, destructuring is a good option as it provides better readability.
Suppose you want to access all the props in the child component then you need not use {} around the argument and then you can use it like props.someProp
const ChildComponent = (props) => (
<div>
<h1>Child Component {props.someProp}</h1>
</div>
)
Are you looking for the ES6 named argument syntax (which is merely destructuring) ?
const ChildComponent = ({ propName }) => (
<div>
<h1>Child Component</h1>
</div>
)
const ChildComponent = (props) => ( // without named arguments
<div>
<h1>Child Component</h1>
</div>
)
Optionally there is a second argument to your function depending of whether you specified a context for your component or not.
Perhaps it would be more helpful wityh a links to the docs. As stated in the first article about functional components. Whatever props passed on to the component is represented as an object passed as first argument to your functional component.
To go a little further, about the spread notation within jsx.
When you write in a component :
<Child prop1={value1} prop2={value2} />
What your component will receive is an plain object which looks like this :
{ prop1: value1, prop2: value2 }
(Note that it's not a Map, but an object with only strings as keys).
So when you're using the spread syntax with a JS object it is effectively a shortcut to this
const object = { key1: value1, key2: value2 }
<Component {...object}/>
Is equivalent to
<Component key1={value1} key2={value2} />
And actually compiles to
return React.createElement(Component, object); // second arg is props
And you can of course have the second syntax, but be careful of the order. The more specific syntax (prop=value) must come last : the more specific instruction comes last.
If you do :
<Component key={value} {...props} />
It compiles to
React.createElement(Component, _extends({ key: value }, props));
If you do (what you probably should)
<Component {...props} key={value} />
It compiles to
React.createElement(Component, _extends(props, { key: value }));
Where extends is *Object.assign (or a polyfill if not present).
To go further I would really recommend taking some time to observe the output of Babel with their online editor. This is very interesting to understand how jsx works, and more generally how you can implement es6 syntax with ES5 tools.
const ParentComponent = (props) => (
<div>
<h1>Parent Component</h1>
<ChildComponent {...props} />
</div>
);
const ChildComponent = ({prop1, ...rest}) =>{
<div>
<h1>Child Component with prop1={prop1}</h1>
<GrandChildComponent {...rest} />
</div>
}
const GrandChildComponent = ({prop2, prop3})=> {
<div>
<h1>Grand Child Component with prop2={prop1} and prop3={prop3}</h1>
</div>
}
You can use Spread Attributes reducing code bloat. This comes in the form of {'somearg':123, ...props} or {...this.props}, with the former allowing you to set some fields, while the latter is a complete copy. Here's an example with ParentClass.js :
import React from 'react';
import SomeComponent from '../components/SomeComponent.js';
export default class ParentClass extends React.Component {
render() {
<SomeComponent
{...this.props}
/>
}
}
If I do, <ParentClass getCallBackFunc={() => this.getCallBackFunc()} />, or if I do <ParentClass date={todaysdatevar} />, the props getCallBackFunc or date will be available to the SomeComponent class. This saves me an incredible amount of typing and/or copying/pasting.
Source: ReactJS.org: JSX In Depth, Specifying the React Element Type, Spread Attributes. Official POD:
If you already have props as an object, and you want to pass it in JSX, you can use ... as a “spread” operator to pass the whole props object. These two components are equivalent:
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}```
Now, let's apply this to your code sample!
const ParentComponent = (props) => (
<div>
<h1>Parent Component</h1>
<ChildComponent {...props} />
</div>
);
I thought I would add a simple ES2015, destructuring syntax I use to pass all props from a functional parent to a functional child component.
const ParentComponent = (props) => (
<div>
<ChildComponent {...props}/>
</div>
);
Or if I have multiple objects (props of parent, plus anything else), I want passed to the child as props:
const ParentComponent = ({...props, ...objectToBeAddedToChildAsProps}) => (
<div>
<ChildComponent {...props}/>
</div>
);
This destructuring syntax is similar to the above answers, but it is how I pass props along from functional components, and I think it is really clean. I hope it helps!
But how do you then retrieve those props if the child component is stateless?
const ChildComponent = ({ *what goes here?* }) => (
<div>
<h1>Child Component</h1>
</div>
)
ChildComponent holds the name and the props will be the argument in the arrow function syntax just as you need:
const ChildComponent = props => (
<div>
<p>{props.value ? props.value : "No value."}</p>
</div>
);
If you Babel-it it will create something like this:
var ChildComponent = function ChildComponent(props) {
return React.createElement(
"div",
null,
React.createElement(
"p",
null,
props.value ? props.value : "No value."
)
);
};
For some reason, what seems to work for me is a variation on Shubham's answer above:
const ChildComponent = props => (
<div>
<h1>Child Component {props[0].someProp}</h1>
</div>
)
Using this
const ParentComponent = ({ prop1, prop2, prop3 }) => (
<div>
<h1>Parent Component</h1>
<ChildComponent {...{ prop1, prop2, prop3 }} />
</div>
);
const ChildComponent = ({ prop1, prop2, prop3 }) =>{
<div>
<h1>Child Component with prop1={prop1}</h1>
<h1>Child Component with prop2={prop2}</h1>
<h1>Child Component with prop2={prop3}</h1>
</div>
}

when to use this.props.children and why

I'm reading this file https://github.com/luispcosta/reddit_clone/blob/master/client/components/Main.jsx
and I don't get line 37, where does the this.props.children come from? I know you can pass props like
<Component name='alan'/>
and you can get name by doing this.props.name to get alan. But this props.children means?
In JSX expressions that contain both an opening tag and a closing tag,
the content between those tags is passed as a special prop:
props.children. There are several different ways to pass children:
https://facebook.github.io/react/docs/jsx-in-depth.html#children-in-jsx
For example:
<Main>
<p>This is a child element</p>
<button>So is this</button>
</Main>
this.props.children in Main will be an array of elements.
// Main.jsx
render() {
return <div>
{this.props.children}
</div>;
}
Would render
<div>
<p>This is a child element</p>
<button>So is this</button>
</div>
In react an element in JSX is represented as
const elem = (<div id="test"> Hi I am a div. </div>);
And there is another alternative way to represent the react element.
So similar element can be represented as -
var elem = React.createElement(
"div",
{ id: "test" },
" Hi I am a div. "
);
createElement has following signature :
React.createElement(component, props, ...children)
Above ...children means any nested JSX elements inside div.
Nested elements in itself can be another react-element and may be more than one of them.
const elem = (<div id="test"> <h1> Hi I am a div. </h1> </div>);
What is props.children?
The returned elem contains light weight object representation.
It has a field called props set. This props field contains custom attributes passed and reference to nested elements i.e child elements.
Now lets see how it is represented
const elem = (<div id="test">Hi I am a div.</div>);
console.dir(elem);
const elem1 = (<div id="test"> <h1> Hi I am a div. </h1> </div>);
console.dir(elem1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
From the logs we can see that props has a property called children. So each parent element contains immediate reference to its children.
"props": {
"id": "test",
"children": "Hi I am a div."
}
When can I use props.children?
When ever you want to get access to children elements in code.
There can be scenario like you want to get access to all of your nested elements.
A simplest example-
You have created a custom button like below -
class MyButton extends React.Component {
render() {
return <button> {this.props.children} </button>;
}
};
// What ever you pass insede <MyButton> and </MyButton>
// You can access it inside your MyButton component via {this.props.children}
const elem = (<MyButton> test1 </MyButton>);
ReactDOM.render(
elem,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
</div>
Another scenario could be you want to loop over your nested children and may be passing some other extra props or may just accessing them -
class MyButton extends React.Component {
render() {
return (
<button onClick={this.props.handleClick}>
{this.props.children}
</button>
);
}
};
class ButtonContainer extends React.Component {
handleClick = () => {
console.log("Clicked");
}
render() {
const childrenWithProps = React.Children.map(this.props.children,
(child) => {
return React.cloneElement(child, { handleClick: this.handleClick });
});
return (
<div>
{childrenWithProps}
</div>
);
}
};
const elem = (
<ButtonContainer>
<MyButton> test1 </MyButton>
<MyButton> test2 </MyButton>
<MyButton> test3 </MyButton>
</ButtonContainer>
);
ReactDOM.render(
elem,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
</div>
There are other scenarios as well with react-router e.g when route changes you want to get access to your children elements to render them on screen.
I have included working code and example where ever possible. I hope this helps you.
It is simple. I will explain by an example
Lets say you have created some component called ComponentDemo.
It is used like this:
<ComponentDemo>
// This component can receive some HTML tags here that will be passed as children props for example:
<div> Hello world</div>
</ComponentDemo>
Then,inside ComponentDemo render function you can use it as:
render(){
// lets use the HTML tags we passed as children here
{this.props.children}
}
what will happen?
ComponentDemo will render
<div> Hello world</div>
which is the value passed by props.children
You can check the API reference of react-router
So, it is just the api provided by react-router which is imported in https://github.com/luispcosta/reddit_clone/blob/master/client/routes.js.
const routes = (
<Route path="/" component={App}>
<Route path="groups" component={Groups} />
<Route path="users" component={Users} />
</Route>
)
class App extends React.Component {
render () {
return (
<div>
{/* this will be either <Users> or <Groups> */}
{this.props.children}
</div>
)
}
}

Categories

Resources