Issue with rendering a component as a prop - reactjs

I have a layout component which acts as follows:
const Layout = ({ children, sider }) => (
<div>
<div>{sider}</div>
{children}
</div>
)
But I can't implement it as expected. I'm hoping to get it implemented as follows:
<Layout sider={Sider}>
Body Content Here
</Layout>
Where Sider is another React component.
However when I do this, my Sider component doesn't render.
I can only get it to work like this:
<Layout sider={<Sider />}>
Body Content Here
</Layout>
How can I update my Layout component so that I can implement sider={Sider} instead of sider={<Sider />}?

Your 2nd approach is correct however if you still want to do that way, do like this
const Layout = ({ children, sider: Sider }) => (
<div>
<div>
<Sider />
</div>
{children}
</div>
)

Another method to handle this is to use React.createElement()
Example:
const Layout = ({ children, sider }) => (
<div>
<div>{React.createElement(sider)}</div>
{children}
</div>
)

Related

React - Call function from non-parent component with state from separate component

I'm attempting to call a function from an AppBar with the state from a child component, like so
// App.js
<BrowserRouter>
<Nav />
<Routes>
<Route exact path={"/"} element={<MyComponent/>}/>
<Routes>
</BrowserRouter>
//Nav.js
function Nav() {
return (
<div>
<h1>Hello World</h1>
<button onClick={logChildState}>Get State</button>
</div>
)
}
// MyComponent.js
function MyComponent() {
const [someState, setSomeState] = useState({
Some state values....
})
return (
<div>
<input />
...more components...
</div>
)
}
logChildState() == "Some state values...."
The goal is to have the AppBar have a button with a function call that captures the state of MyComponent. As this is a simplified example, I will just say that the state should exist in the child, and it's not possible to hoist the state to App.js - because of this, I don't see a way to accomlish what I'm looking for easily, I've looked at possibly achieving this using context or an observable but it would be quite messy.
I'm wondering what the best way to tackle this kind of issue would be, or if my best choice would just be to have the "button" in Nav.js in the MyComponent.js.
Thanks
You can add the function as a prop like this:
//Nav.js
function Nav({logChildState}) {
return (
<div>
<h1>Hello World</h1>
<button onClick={() => logChildState('send this message')}>Get State</button>
</div>
)
}
And in your app Component you can simply take it as a prop like this:
<Nav logChildState = {logChildState}/>
and if you want to print the message comming from Nav component simply do this in App.js
const logChildState = (message) => {
console.log(message);
}
Hope that helps!

React Smooth Scroll into specific location in my reusable component?

So I originally created a smooth scroll effect with regular HTML css and js, but I'm trying to convert it into react, but I'm not sure if I am doing it properly.
I have a Navbar component and just set the path
<NavLinks to='/#posts'>Posts</NavLinks>
Then I have my Main Content sections which are reusable components that receive data and display a different design based on what data I pass in.
function InfoSection({
lightBg,
id
}) {
return (
<>
<div
id={id} //Passed in the id value
className={lightBg ? 'home__hero-section' : 'home__hero-section darkBg'}
>
// Rest of my JSX is inside here
</div>
</>
);
}
Then in my Data file I'll pass in the values
export const homeObjThree = {
id: 'posts',
lightBg: true,
}
Then I display my reusable components in my index.js page
function Home() {
return (
<>
<InfoSection {...homeObjThree} />
</>
);
}
Then I import that into my App.js file
function App() {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<Router>
<Sidebar isOpen={isOpen} toggle={toggle} />
<Navbar toggle={toggle} />
<Home />
<Footer />
</Router>
);
}
So when I inspect, it shows the Home HTML with an id="posts" which I set from my data file, but when I click on the Post nav menu item it doesn't scroll down to the section. Nothing actually happens, so I can't tell if my approach even works for padding in ids into my data file or if I would need to write scroll functions to implement it.

How to use nested components defined as constant with arrow functions in React?

If I comment out {children} from Layout this works as expected.
Otherwise, error
index.js Invariant Violation: Objects are not valid as a React child (found: object with keys {children})
Why?
layout.js
const Layout = (children) => (<div>
<Header />
{children}
</div>)
export default Layout
index.js (root component)
const IndexPage = () => (
<Layout>
<h1>Hi people</h1>
</Layout>
)
export default IndexPage
(children) =>
Despite what you've called it, this is the entire props object, not just the children. Either use destructuring to pick the children prop:
({ children }) =>
Or access props.children explicitly:
(props) => (
<div>
<Header />
{props.children}
</div>
)

React Map each Children and add css style to each children

I need to style each children when render
My first Component is side bar
Mainpage.js
<Sidebar>
<Mycomp>
<p>one</p>
<p>two</p>
<p>three</p>
</Mycomp>
<Mycomp postion="bottom">
<p>one</p>
<p>two</p>
<p>three</p>
</Mycomp>
</Sidebar>
In my Sidebar.js I have map for each children like this
const test=Children.map((this.props.children, child) => (
<div className="hello">
{child}
</div>
))
But the class hello div is only wrapped with Mycomp component
I need to wrap class hello div tag to each p inside Sidebar.js
Not sure if this is what you want. But this how you would inject styles to each components of Children
const test = Children.map(this.props.children, Component=>(
<Component className="hello" />
))
const test = this.props.children.map(child => (
<div className="hello">
{child}
</div>
))
const test=Children.map(this.props.children,child=>(
{Children.map(child.props.children, child=> <div className="hello">{_child}</div>)}
))
try this!

Call Parent function from route this.props.children in React

I have below layout and in this layout Route pages are being rendered.
const Layout = () => {
return (
<main className="fadeIn animated">
{ this.props.children }
</main>
)
}
return (
<React.Fragment>
<Layout callFunction={ () => console.log('callFunction') }/>
{/*I will set the state using callFunction Function and then pass in modal*/}
<Modals data={this.state}/>
</React.Fragment>
)
The page that is being rendered inside the children using route is below
class Page extends React.Component {
return (
<React.Fragment>
ROUTE PAGE IS . I would like to call callFunction from here
<button onClick={parent.callFunction}>CALL</button>
</React.Fragment>
)
}
I would like to call callFunction function of Layout Component from Children Page in reactjs
If i understand you correctly, you wish "Layout" to run the "loadLayout" function
if so, just let the Layout know what it's receiving
const Layout = ({loadLayout}) => {
loadLayout()
return (
<main className="fadeIn animated">
{ this.props.children }
</main>
)
}
I'm not sure this is what you meant, we need more info, who loads who

Resources