This question already has answers here:
How to pass props to {this.props.children}
(32 answers)
Closed 1 year ago.
I have a simple component:
const Test = ({header}) => <View> <Header /> </View>`
and call it like so:
<Test header={<View> Test </View} />
but it fails saying:
JSX element type 'Header' does not have any construct or call signatures
How do I fix this? I need to render it like <Header /> so I can pass further props down to it
I don't want to render it like {header} this.
If you want to pass props to your children have a look at the React API with the function cloneElement
You can foreach your children using React.Children
function Component({ children, ...props }) {
const newChildren = React.Children.map(children, child => {
return React.cloneElement(child, { ...child.props, ...props });
});
return (
<div>
{newChildren}
</div>
);
}
You can make it like this:
const Test = ({children}) => <View> {children} </View>
and use it like this:
<Test>
<Header/>
</Test>
For more read the docs composition-vs-inheritance
Let me know if you are trying to achieve this
const Test = ({header: Header}) => <View> <Header /> </View>
you can try to do this
const Test = ({header})=>{
return <View>
{React.cloneElement(header, ObjectContainingPropsYouWantToPass)}
</View>
}
source
Related
const Section = ({ text, changeFn }) => {
return(
<>
<Content text={text} changeFn={changeFn}/>
<Content text={text} changeFn={changeFn}/>
<Content text={text} changeFn={changeFn}/>
</>
)
}
const Content = ({ changeFn, text }) => {
const [ textCont, setText ] =useState('text')
return(
<>
<div>{textCont}</div>
<button onClick={changeFn}>Edit</button>
</>
)
}
const Form = ({ changeFn, setContent }) => {
let inputRef = useRef()
const applyChangefn = () => {
setContent(inputRef.current.value)
changeFn()
}
return(
<>
<input ref={inputRef}/>
<button onClick={applyChangefn}>Save</button>
</>
)
}
I want to make a component which exists as example with its own usestate in Content component.
Then i want to send it multiplied by 3 times into Section component.
First question is how to send props between sibling components
Second question is how to make 3 same components which have its own useState state. I mean 3 same components with independent usestate.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
Is there any way to add attributes to the Welcome function-component, other than by creating a separate line such as <Welcome name="Sara" />?
Using .map() you can render the elements of an array as:
function App() {
const elements = ["Sara", "Cahal", "Edite"]
return (
<div>
{ elements.map((e, i) => <Welcome key={i} name={e} />) }
</div>
);
}
Additionally I suggest to read through the documentation of Rendering Elements and Lists and Keys.
This is not the standard way of defining props, but I quite like the syntax of using an object with the spread operator to define props if you have variables with the names of the props you want.
function App() {
const elements = ['Sara', 'Cahal', 'Edite'];
return (
<div>
{elements.map((name, key) => (
<Welcome {...{ name, key }} />
))}
</div>
);
}
You can create an array with names and after loop through it:
const names = ["Sara", "Cahal", "Edite"];
return (
<div>
{names.map(name => <Welcome key={name} name={name} />)}
</div>
)
I'm trying to create a custom component and put other components like or inside this component but it doesn't seem to be working (nothing shows up). Could someone be kind enough to provide an answer or perhaps correct my understanding where it's gone wrong?
For example, if I have a Home page and inside there's a Card component where within there's Text and View components.
import React from 'react'
import {Text, View} from 'react-native'
const CoolCard = ({props}) => {
return(
<View>
{props}
</View>
)
}
const Home = () => {
return(
<View>
<CoolCard>
<Text>This is a cool card!</Text>
</CoolCard>
</View>
)
}
export default Home
This doesn't work but if I do
const Home = () => {
return(
<View>
<CoolCard props = {
<Text>This is a cool card!</Text>
}/>
</View>
)
}
this works, which I understand. Is there a way for me to write the first example to make it work?
Thanks a lot!
You should use the 'children' prop to get the children
const CoolCard = ({children}) => {
return(
<View>
{children}
</View>
)
}
const Home = () => {
return(
<View>
<CoolCard>
<Text>This is a cool card!</Text>
</CoolCard>
</View>
)
}
export default Home
In order to "wrap" a component inside another you can use props.children this is how it looks in a react functional component :
Wrapper component:
const WrapComponent = ({children}) => (
<Text>
{children}
</Text>
)
Then you can wrap it around any valid JSX:
<WrapComponent> {/* put stuff here */} </WrapComponent>
You can find more in the official react documentation
I have a simple React component:
const FullContainer = ({
backgroundColor,
children,
}) => (
<Container
backgroundColor={backgroundColor}
>
{children}
</Container>
);
I'm currently destructing the only two properties I expect my component to use, but I'd also like to pass in props and spread it in as well:
const FullContainer = (props, {
backgroundColor,
children,
}) => (
<Container
backgroundColor={backgroundColor}
{...props}
>
{children}
</Container>
);
Oddly enough, this breaks my page with no errors. I must be doing something wrong. Is my syntax wrong?
You can make use of rest spread syntax that provides the remaining properties which aren't destructured as an array like
const FullContainer = ({
backgroundColor,
children,
...props
}) => (
<Container
backgroundColor={backgroundColor}
{...props}
>
{children}
</Container>
);
I am using React-Router v4 to navigate in my React app. The following is a component wrapped in the withRouter() function to make it able to change route on click:
const LogoName = withRouter(({history, props}) => (
<h1
{...props}
onClick={() => {history.push('/')}}>
BandMate
</h1>
));
As you can see I pass the props to the component, which I need in order to change the class of the component. The problem here is that props is undefined in the <LogoName> component. I need to be able to change the class of this component when I click on another component, like this:
<LogoName className={this.state.searchOpen ? "hidden" : ""} />
<div id="search-container">
<SearchIcon
onClick={this.handleClick}
className={this.state.searchOpen ? "active" : ""} />
<SearchBar className={this.state.searchOpen ? "active" : ""}/>
</div>
Here is how I handle the click. Basically just setting the state.
constructor(){
super();
this.state = {
searchOpen: false
}
}
handleClick = () => {
this.setState( {searchOpen: !this.state.searchOpen} );
}
Is there a way for me to pass props to a component that is wrapped inside the withRouter() function or is there a similar way to create a component which has the ability to navigate with React-Router and still receive props?
Thanks in advance.
The problem is that while destructuring, you want to destructure props but you are not passing any prop named props to LogoName component
You can change your argument to
const LogoName = withRouter((props) => (
<h1
{...props}
onClick={() => {props.history.push('/')}}>
BandMate
</h1>
));
However you can still destructure the props like #Danny also suggested by using the spread operator syntax like
const LogoName = withRouter(({history, ...props}) => (
<h1
{...props}
onClick={() => {history.push('/')}}>
BandMate
</h1>
));
You're close, just spread the props in your function signature as well:
const LogoName = withRouter(({ history, ...props }) => (
<h1
{...props}
onClick={() => {history.push('/')}}>
BandMate
</h1>
));
This worked for me:
import {withRouter} from 'react-router-dom';
class Login extends React.Component
{
handleClick=()=>{
this.props.history.push('/page');
}
render()
{
return(
<div>
.......
<button onClick={this.handleClick()}>Redirect</button>
</div>);
}
}
export default withRouter(({history})=>{
const classes = useStyles();
return (
<Login history={history} classes={classes} />
)
});