React Map each Children and add css style to each children - reactjs

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!

Related

How to wrap first element child from render function of React functional component?

How i can wrap child element/s from render function in React component? For example, i have component:
React functional component:
const Component = () => (
<div>
<p>Some p element</p>
</div>
)
and i want to wrap only <p> element with something else. I want this result after wrapping:
Component after wrapping:
const Component = () => (
<div>
<Wrapper>
<p>Some p element</p>
</Wrapper>
</div>
)
How can i do it? Thx

Warning message "Function components cannot be given refs" when using an own child coponent with Dropzone

When creating an own child function component and use it within <Dropzone>...</Dropzone>, I see the following warning message, inside the console:
react-dom.development.js:67 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Check the render method of `Dropzone`.
at MyContainer (http://localhost:3000/static/js/bundle.js:83:12)
at http://localhost:3000/static/js/bundle.js:35421:23
at header
at div
at App
My code looks like that:
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Dropzone from 'react-dropzone';
export const MyContainer = ({...other}) => (
<div {...other}/>
);
export function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p data-testid="projectNameInput">
Hello World
</p>
<Dropzone onDrop={acceptedFiles => console.log(acceptedFiles)}>
{({getRootProps, getInputProps}) => (
<MyContainer {...getRootProps()}>
<section>
<div>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
</section>
</MyContainer>
)}
</Dropzone>
</header>
</div>
);
}
export default App;
Everything seems to work as expected with the Dropzone and the message disappears, when I don't use {...getRootProps()} as attribute-list of MyContainer.
Of course I have checked the react documentation about forwardRef (https://reactjs.org/docs/forwarding-refs.html) and searched for an explanation of this issue. However all explanations do not really fit to my case, because I don't use any reference here at all. At least I don't see the usage of a reference.
Is this an issue of react-dropzone or do I use the dropzone wrongly?
I ran into the same warning a while back and found that when you call getRootProps it returns several different props, one of them is ref:
const { ref, ...rest } = getRootProps();
So you are actually using ref even though it is not obvious. If you want to use Dropzone on your custom component (MyContainer in your case), you have to add Ref forwarding on MyContainer:
const MyContainer = React.forwardRef(ref, {...other}) => (
<div ref={ref} {...other}/>
);
OR
You can extract the ref value and pass it as a custom prop:
// MyContainer
export const MyContainer = ({ innerRef, ...other}) => ( // make component accept prop innerRef which will be passed to the div's ref prop
<div ref={innerRef} {...other}/>
);
// App (omitted code before and after)
<Dropzone onDrop={acceptedFiles => console.log(acceptedFiles)}>
{({ getRootProps, getInputProps }) => {
const { ref, ...rootProps } = getRootProps(); // extract ref
return (
<MyContainer innerRef={ref} {...rootProps}> // pass ref via custom prop innerRef
<section>
<div>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
</section>
</MyContainer>
);
}}
</Dropzone>
Hope it helps!

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>
)

Issue with rendering a component as a prop

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>
)

How to pass className as props?

*I want to pass React.Element's className as props from component , i am new react. can i pass classname as props ?
I am trying to achieve dynamic theme change where i can pass different props and chnage component looks.
css
<style>
.c1 {
color: red
}
.c2 {
color: teal
}
</style>
// code does not works
const Comp = ( props) => <h1 {props.className} > Hello , World </h1>
ReactDOM.render(<Comp className="c1"/> ,
document.getElementById("root"))
// but this code works
const Comp2 = (props) => <h1 className="c1" > Hello , World </h1>
ReactDOM.render(<Comp2 />, document.getElementById("root"))
You are almost there, as you are passing className="c1" to Comp2 component, you just need to have a className attribute to hold this props as
const Comp = ( props) => <h1 className={props.className} > Hello , World </h1>
ReactDOM.render(<Comp className="c1"/> , document.getElementById('root'));
Demo
You need to pass the dynamic classname from prop to the element as -
<h1 className={props.classname} > Hello , World </h1>
ReactDOM.render(<Comp2 classname='c1'/>, document.getElementById("root"))
You have to pass className as a prop just like below:
const Comp = props => <h1 className={this.props.className}>Hello World</h1>

Resources