Is it possible to pass a prop containing a function to any child ? More precisely I would like to pass a function from a component to every {children} component :
<>
<Navbar />
<main>{children}</main>
<Footer />
</>
You should then use something like Context for that.
The props you pass to your Context Provider will be available to all it's children. But you won't get them via props, you need to get them via the Context Consumer.
But the good thing is Context Consuming hooks are available to make it easy to do so.
Related
So in my main component, I send props to a child component like this:
<div className={styles.navBar}>
<MasterNavBar color={false} scrollChange={true} />
</div>
MasterNavBar gets access to the props correctly, but I need MasterNavBar to pass those props to a child component called NavBar, which I currently do like this:
<NavBar props />
However, when I do this, the props are not accessible in my NavBar component file. For example, in NavBar, doing props.color to get my color prop returns undefined. So, am I passing my props incorrectly, or am I missing something else?
As Antonio Pantano said, you can pass the whole props to the <NavBar {...props}/> component, but this is a bad practice way. This article explained why it is a bad practice way. So you can pass the MasterNavBar props to its child in these two ways:
const MasterNavBar = (props) => {
/*
rest of your code
*/
return <NavBar color={props.color} scrollChange={props.scrollChange}/>
}
or
const MasterNavBar = ({color, scrollChange}) => {
/*
rest of your code
*/
return <NavBar color={color} scrollChange={scrollChange}/>
}
You can change the name of NavBar props as you wish, and you access them in the NavBar component by these names.
That's depend on which props NavBar is expecting. If you don't care about typing (either with typescript or react PropTypes) you can simply do like this:
<NavBar {...props} />
However this is not the best approach and can lead to performance issues.
Currently working a group project and I've been looking over the code the group wrote and I'm curious if there is a better way to pass props to n children components that change the state of the top-level App component.
currently we have something like this:
return (
<div>
<header className="navBar">
// NavBar is an example for the question
<NavBar
showSplash={this.state.showSplash}
displayAllSearchResults={this.displayAllSearchResults}
searchBarDisplay={this.state.showCard}
updateResults={this.updateResults}
selectResult={this.selectResult}
searchResults={this.state.searchResults}
showSuggestions={this.state.showSuggestions}
/>
</header>
<section className="App">
<article className="mainContent">{card}</article>
</section>
<div className="appBackground" />
</div>
);
All of these methods (which there are probably too many) are being passed into the NavBar component that itself is composed with a SearchBar component which also needs that giant block passed into it in order to change the state all the way back at the top-level App. This feels wrong, is there a solution or better approach to passing all these props down?
You can use the spread operator like this :
<NavBar {...this.state} />
It will pass you state properties as props to the navbar.
In you Navbar component, you can get the value of showSplash in state from props.showSplash
If you want to pass the data into a child component of Navbar, you can do something like this :
<ChildComponent {...props} /> // if Navbar is a functional component
<ChildComponent {...this.props} /> // if Navbar is a stateful component
Reference:
Spread in object literals
Here is a sample stackblitz for illustration.
If you want a data to be accessible by all the child components, then you have following options:
React Context
Redux or state management library like flux etc.
Or you could follow #Abdelkarim EL AMEL answer if that soughts out you issue for now.I would suggest take a look at the above mentioned options and if setting a global state which can be accessed anywhere in the app helps you to not send prop to each component explicitly. I would prefer to use a global state for variable which are common and needs to be accessed by all the child of the root app.
For example a button component to change the theme of the app. It changes the state of the root app and is accessible by every component.
I think this is actually entirely OK, and would recommend leaving it.
If you don't like seeing it itemized in the return of the render method you could keep them all in an object called navbarprops and just spread that in. I still prefer it as is though!
I have a bunch of components that require the same prop, and going through them individually to add the JSX is cumbersome, can I create a piece of JSX in the parent that will be passed to these child components as a prop?
Here's basically what I want to do:
function App(props) {
/*not part of the actual code, but I want to
pass this h1 tag into the bottom components as a prop*/
<h1>{props.heading}</h1>
<Home heading="Home"/>
<AboutMe heading="About Me"/>
<Contact heading="Contact"/>
}
I know the code above isn't how you're supposed to do it, but is there a way I can accomplish that functionality?
Yes, that's possible. Just assign your JSX component to a variable and pass that variable as a prop. You have the right idea.
For example:
var customHeader = <h1>Here's a custom component</h1>
You can also set customHeader to a React component such as: var customHeader = <CustomHeader />
You can pass through <MyComponent header={customHeader}/> and in your render function of MyComponent page, you can simply use {this.props.header} to load your component. This can be repeated for any number of components.
Edit based on comments. In that case, I would wrap the component in a function. For example:
getCustomHeader = (title) => {
return <MyHeader
headerTitle={title}
/>
}
Now, in your render function, you can call getCustomHeader.
render() {
return <div>
<MyComponent1 header={this.getCustomHeader("Title A")} />
<MyComponent2 header={this.getCustomHeader("Title B")} />
</div>
}
What would be the idiomatic and/or more effective way of handling a situation whereby the parent component wants the child to render some custom JSX?
a render callback?
or passing a component instance directly into the prop?
Example:
// Option 1
// -
const rightChild = <View />
<NavigationBar rightChild={rightChild} />
// Option 2
// -
const renderRightChild = () => <View />
<NavigationBar renderRightChild={rightChild}>
(lambdas are used for simplicity, I am aware of the performance implications)
This:
const rightChild = <View />
// ...
<NavigationBar rightChild={rightChild} />
...isn't "passing JSX into the prop." It's passing a component instance. The JSX is processed by const rightChild = <View /> (turned into React.createElement call) and the result (a component instance) is stored in rightChild. That's normal, though it's usually as a child (ending up on the children prop) rather than a separate named prop. But either way, it's a prop, so...
As far as I know, that would be the standard way to do it.
Either way will work. The case for when you really want to use a render prop is when you will need the props passed from NavigationBar in order to render the component or fragment. The benefit to passing in a component is that you will not be passing in a new function to be rendered each time. From a performance standpoint it would be a bit easier to get it to not for a re-render.
I'm trying to send function reference to imported component. So it's better I use ref attribute or props ?
I want to find an optimum and standard method.
<MyComponent ref="ListView" />
Or this method:
<MyComponent show="this.showModal" hide="this.hideModal" />
There wouldn't be an effect if you pass functions as a string (like "this.showModal").
Pass them down in curly braces:
<MyComponent show={this.showModal} hide={this.hideModal} />
Refs purpose is to manipulate DOM directly, not to pass something to the component. For example, you may want to manipulate DOM with jQuery
We don't use refs for event handling it is preferable to pass handlers as props to child component using JSX sytax with {} braces.
You want to send eventhandler to child component from parent if i understand your question correctly?
parent.js
class ParentComponent extends Component {
handler = () => {
console.log("handler click">
}
render() {
return (
<div>
<Child handler={this.handler} />
</div>
);
}
}
child.js
const Child = ({ handler }) => (
<Button onClick={handler} />
)
EDIT:
I understood your question, if you have a lot of method you can use ...props but also you can pass props as separated methods.
I think you're referring to the differences between controlled and uncontrolled components :
uncontrolled-
https://reactjs.org/docs/uncontrolled-components.html
controlled-
https://reactjs.org/docs/forms.html
The answer for that is depending on your component "logic", if you want to controll it by the DOM(using refs) or by the component itself.