How to pass className as props? - reactjs

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

Related

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 can I access the props for a nested component in React?

I want to pass props to my nested component but the problem here is the inner card component that is not showing the data passed to it neither the Inner text props nor the inner pct props.
This is my index.js
const tst = () => {
return (
<div className="d-flex">
<Card text={"occupied"} pct={75} width={250}/>
<Card width={370}>
<InnerCard2 Innertext={"Compeleted"} InnerPct={25}/>
<InnerCard2 Innertext={"WIP"} InnerPct={50}/>
<InnerCard2 Innertext={"Upcoming"} InnerPct={25}/>
</Card>
}
This is my card component:
import React from 'react';
import InnerCard2 from './InnerCard2';
class Card extends React.Component {
render() {
var {text="", pct=0, } = this.props
const style = {
width: this.props.width + 'px',
marginRight: '10px'
}
return (
<div className="white-box v-align ht-100" style={style}>
<div className="flex-one"></div>
<div className="wd-80">
<div className="fs-xl fw-bold" style={{ color: '#142654' }}>{pct} %</div>
<div className="small-text">{text}</div>
</div>
</div>
);
}
}
export default Card;
This is my inner card component:
import React from 'react';
class InnerCard2 extends React.Component {
render() {
var {InnerText="", InnerPct=0} = this.props
return (
<div className="wd-80">
<div className="fs-xl fw-bold" style={{ color: '#669900' }}>{InnerPct}%</div>
<div className="small-text">{InnerText}</div>
</div>
);
}
}
export default InnerCard2;
At a glance I'm seeing two problems:
First, InnerCard is expecting a property called InnerText but you're passing it a property called Innertext. Casing matters. Either change the name of the property in the component or change the name of the property being passed to the component.
Second, the Card component is ignoring its children property, so it doesn't render them. By convention any child components wrapped by a component are passed to it as a prop called children. Add children to the prop deconstruction:
var {text="", pct=0, children } = this.props
And display the children wherever you want to in the rendering. For example:
<div>
{children}
</div>

CSSTransition nodeRef for component with direct children

I want to get rid of the warning on StrictMode for findDOMNode when using react-transition-group but I stumbled upon an issue.
My <Slide> component looks like this:
class Slide extends React.Component {
nodeRef = React.createRef();
render() {
return (
<CSSTransition
in={this.props.in}
timeout={ANIMATION_DURATION}
mountOnEnter={true}
unmountOnExit={true}
classNames={{
enter: "slideEnter",
enterActive: "slideEnterActive",
exit: "slideExit",
exitActive: "slideExitActive"
}}
nodeRef={this.nodeRef}
>
{this.props.children}
</CSSTransition>
);
}
}
It receives a Drawer element as children, the Drawer component looks like this:
class Drawer extends React.Component {
render() {
return (
<div className="drawer">
<button onClick={this.props.onClose}>close me</button>{" "}
<div>This is my drawer</div>
</div>
);
}
}
I cannot wrap the children element with a HTML tag (to attach a ref <div ref={this.nodeRef}>{this.props.children}</div> because it breaks the animation of the content. (I'm using this for children that are different drawers with position absolute)
I've also tried with cloneElement but it still doesn't work (with the code from below it behaves like this: 1. in no animation, 2. out no animation, 3. in animation works but I get the warning findDOMNode so it seems that nodeRef is sent as null, 4. out animation does not work.
const onlyChild = React.Children.only(this.props.children);
const childWithRef = React.cloneElement(onlyChild, {
ref: this.nodeRef;
});
Is there any solution for this situation? Thanks!
The problem is that nodeRef needs to point to a DOM Node, as the name suggests, in your case it points to an instance of the Drawer class. You have two options:
Pass the ref through another prop, e.g. forwardedRef, and in the Drawer class pass that prop to the root element:
React.cloneElement(onlyChild, {
forwardedRef: this.nodeRef,
})
<div ref={this.props.forwardedRef} className="drawer">
Convert Drawer to a function component and use React.forwardRef:
const Drawer = React.forwardRef((props, ref) => {
return (
<div ref={ref} className="drawer">
<button onClick={props.onClose}>close me</button>{" "}
<div>This is my drawer</div>
</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!

React props from parent to children

I'm a debutant with react, i read the doc. It's a general question.
I understand how to pass a props from a child component to a parent component. But, I don't understand how to pass a props from a parent component to the child component.
So in the picture, to pass a props from list to app, i do that :
in list component :
interface Props {
onCreateDoc : () => void
}
And in my app component :
I call list with the props :
<List onCreateDoc={this.onCreateDocCb}/>
And i implement the function :
onCreateDocCb = () =>{
// code of function
}
But I don't know how to pass a props from app to form. How can i do that ? Thank you
It's easier to understand how to pass props then how to receive props.
You add props to your Form Component that way:
const bar = "bar"
const fooBar = () => console.log("fooBar")
<Form stringProps="foo" varProps={bar} funcProps={fooBar}/>
Inside your Form Component you can acces it via this.props.stringProps.
Here you find examples: https://facebook.github.io/react/docs/components-and-props.html
Edit: Here is a snippet with a App and a Form Component and props passed from App to Form
// Example stateless functional component
const Form = ({ label }) => (
<div style={{color: "blue"}}>{label}</div>
);
// Example class component
class App extends React.Component {
render() {
const {title} = this.props;
return (
<div>
<div>{title}</div>
<Form label="label from props" />
</div>
);
}
}
// Render it
ReactDOM.render(
<App title="title from props" />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Resources