React function to wrap a jsx element - javascript

I'm trying to create a function that will return a jsx element wrapped with and elements. How to do this?
In my code, I have a lot of the following:
<Top />
<Home />
<Bottom />
<Top />
<About />
<Bottom />
<Top />
<Contact />
<Bottom />
<Top />
<Blog />
<Bottom />
<Top />
<API />
<Bottom />
etc.
How can I make a function which takes say <Home /> as an input parameter and returns a wrapped jsx element?
I've tried:
function wrap(???){
return (
<Top />
//what goes here????
<Bottom />
)
}
I'm afraid I'm still getting used to the syntax and can't figure it out

first, you need to wrapp the return with a root element, a div for exp, or a Fragment which is released in React 16.2, in this exp i used a div:
function wrap(Wrapped) {
return (
<div>
<Top />
<Wrapped />
<Bottom />
</div>
)
}
Edited: you could use the render children method also:
const WrapperExp = props => {
return (
<div>
<h1>top</h1>
{props.children}
<h1>bottom</h1>
</div>
)
};
const App = () => (
<WrapperExp>
<h2>tada...</h2>
</WrapperExp>
);
take a look at this codesandbox exp.

The correct syntax should be
function wrap(component) {
return (
<Top />
{component}
<Bottom />
);
}
and maybe if you use wrap in a render method
render() {
const aComponent = (<Home/>);
return (
{wrap(aComponent)}
);
}

Related

React table rowProps prop doesnt log anything

[Basically, we're using this from one of our libraries. But the thing is while using it through our package the rowProps prop doesn't work]
(https://i.stack.imgur.com/fER2B.png).
import { AdvancedTable } from "ims-ui-kit";
function Table(props) {
console.log(props)
return <AdvancedTable {...props} />;
}
export default Table;
Here is another screenshot of the prop passing through the table we are using. It doesn't log anything.
[enter image description here]
<>
{alert}
<div className="content">
<ReactTable
// hasBulkActions={true}
data={data}
filterable
{...rest}
resizable={false}
columns={columns.slice()}
defaultPageSize={10}
showPaginationTop
showPaginationBottom={false}
className="-striped -highlight"
rowProps={(row) => {
onclick = () => {
console.log("hello", row);
};
}}
/>
<Modal title="Risk management">
<RiskDetail isModalOpen={isOpen} />
</Modal>
</div>
</>

How to simplify overriding props in React?

I have an If statement and returning the same component with the extra props based on the state. Any idea how to simplify this? Can I use recursion? Any idea?
iconRight is only difference.
renderInput = () => {
if (isLoading) {
return (
<Input
iconRight={(
<Spinner />
)}
autoComplete="off"
id="unique-id-2"
aria-autocomplete="both"
/>
);
}
return (
<Input
autoComplete="off"
id="unique-id-2"
aria-autocomplete="both"
/>
);
}
}
You can spread props onto the component:
renderInput = () => {
const props = {
autoComplete: 'off',
id: 'unique-id-2',
'aria-autocomplete': 'off'
};
if (isLoading) {
return (
<Input
iconRight={(
<Spinner />
)}
{...props}
/>
);
}
return (
<Input {...props} />
);
}
}
But i'd suggest changing your Input component to accept a loading prop and let the Input component handle that logic. It'll make your consuming code a lot easier to read also.
I think your function can be shortened to the following;
renderInput = () => (
<Input
iconRight={isLoading ? (<Spinner />) : null}
autoComplete="off"
id="unique-id-2"
aria-autocomplete="both"
/>
)
If you don't already, inside your Input component, you should check if the iconRight prop is not null, and only render it then.
You can try this:
renderInput = () =>(
<Input
iconRight={
isLoading && (
<Spinner />
)}
autoComplete="off"
id="unique-id-2"
aria-autocomplete="both"
/>
)

multiple items inside the rightIconButton of a MaterialUI ListItem

I want to attach multiple items to the rightIconButton inside a ListItem.
I'm using Material UI v0.20 and React#15.6.2
<ListItem
rightIconButton={
<span>
<RaisedButton />
<TrashIcon />
</span>
}
/>
How can i wrap the items to avoid the warning?
Warning: Unknown prop onKeyboardFocus on span tag. Remove this prop from the element.
Try using HOC:
function Single() {
return (
<div>
<RaisedButton>Hello</RaisedButton>
<RaisedButton>wORLD</RaisedButton>
</div>
);
}
function App() {
return (
<MuiThemeProvider>
<List>
<ListItem rightIconButton={<Single />} />
</List>
</MuiThemeProvider>
);
}
A custom component will help to remove the warning:
function GroupedButtons(props) {
return (
<span>
<RaisedButton>Hello</RaisedButton>
<RaisedButton>WORLD</RaisedButton>
</span>
)
}
...
function App() {
...
<ListItem
rightIconButton={
<GroupedButtons />
}
/>
Working example:

React Router 4 passing props through Route render doesn't work

This question has been asked, but other answers aren't solving this for me. I want to pass the signInWithEmail handler function from my <App /> component down through <Layout /> and then to the <SignIn /> component via a <Route />.
The way to do this is apparently via the render attribute on the Route, but for me it just renders ignores my onSubmit. In React dev tools I just see the default Route props, even though I can see my handler function(s) in the <Layout /> element showing up as props.signInWithEmail. They don't make it to the <SignIn /> element.
What am I missing? Thanks.
const Layout = (props) => (
// i can console.log(props) here and see props.signInWithEmail
<div className="layout">
// header etc...
<main>
<Switch>
// ... other routes
<Route
path="/signin"
render= {(props) => <SignIn onSubmit={props.signInWithEmail} />}
/>
</Switch>
</main>
// footer etc...
</div>
)}
render part of App:
render() {
return (
<div className="App">
<BrowserRouter>
<Layout
signInWithEmail={this.signInWithEmail}
signUpWithEmail={this.signUpWithEmail}
signOut={this.signOut}
state={this.state}
/>
</BrowserRouter>
</div>
);
}
It happens because you overriding props within arrow function.
Try to destructure Layout prop like that:
const Layout = ({signInWithEmail}) => (
// i can console.log(props) here and see props.signInWithEmail
<div className="layout">
// header etc...
<main>
<Switch>
// ... other routes
<Route
path="/signin"
render= {() => <SignIn onSubmit={signInWithEmail} />}
/>
</Switch>
</main>
// footer etc...
</div>
)}

How pass a prop in my route from my component to a child component with an 'onClick'

I've got a component in my react app with an idTeam.
When I click on a Button, in a child component with an event onClick, I want to pass on my Details page with this idTeam in my props.
Here are my Routes & my Switch:
{/* ... other components ... */}
<Menu.Item
name='details'
active={activeItem === 'details'}
onClick={this.handleItemClick}
>
<Link to="/details">Détails</Link>
</Menu.Item>
</Menu>
</div>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/equipes' component={Teams} />
<Route path='/details/:idTeam' component={Details} />
<Route component={Page404} />
</Switch>
My parent Component:
const teamsComponents = this.state.teamsList.map((team)=> (
<TeamItem
key={team.idTeam}
strTeamBadge={team.strTeamBadge}
strTeam={team.strTeam}
strStadium={team.strStadium}
goToDetails={this.goToDetails(team.idTeam)}
/>
))
And the function goToDetails():
goToDetails = (idTeam) => {
return <Link to={`/details/${idTeam}`} render={(props) => <Details
idTeam={idTeam} {...props} /> } />
}
And the Child Component:
onReceiveDetails = () => {
this.props.goToDetails()
console.log('mes props 2 :' , this.props.params.idTeam);
}
<Button
icon='group'
label={{ as: 'a', basic: true, content: 'Détails',
color:'black' }}
labelPosition='right'
color='black'
onClick={() => this.onReceiveDetails()}
/>
When i'm trying to click on my button i've got "_this.props.goToDetails is not a function"...
Any idea to keep this idTeam on Details Page ?
In your "Parent Component" try passing the goToDetails prop as goToDetails={() => this.goToDetails(team.idTeam)} instead of the way you're currently doing it. This will make sure a function gets passed down to the child component (I assume TeamItem).
Your parent component would then look like:
const teamsComponents = this.state.teamsList.map((team) => (
<TeamItem
key={team.idTeam}
strTeamBadge={team.strTeamBadge}
strTeam={team.strTeam}
strStadium={team.strStadium}
// -> change the line below
goToDetails={() => this.goToDetails(team.idTeam)}
/>
))
Also, in your goToDetails function, you may want to use this.props.history.push(<YOUR-PATH>) like this:
goToDetails = (idTeam) => {
this.props.history.push(`/details/${idTeam}`);
}
<TeamItem
key={team.idTeam}
strTeamBadge={team.strTeamBadge}
strTeam={team.strTeam}
strStadium={team.strStadium}
goToDetails={() => this.goToDetails(team.idTeam)}
/>
))
Your function is invoked when the component renders, try using an arrow function

Categories

Resources