Passing css classes through props to a children component - html

So, i have a css file with determined classes, lets say (class1,class2,class3,etc) and i need to make a presentational component that passes through props their properties to a child component. if the called name in the child component then the properties of the css class are available to use.

props.children = the component(s) nested inside that component. We can use React.cloneElement() in order to pass properties into the child.
const PresentationalComponent = ({ children }) => {
const hardCodedClassName = '.some-class';
return (
<>
{React.cloneElement(props.children, { className: hardCodedClassName })}
</>
)
}
// Usage
<PresentationalComponent>
<ChildComponent />
</PresentationalComponent>

Related

How can I get the height of an element after it has rendered?

I want to get the height after an element is rendered. The element is inside another component than which I want to detect it in.
I know I can do it like this:
const heightOfStepper = document.getElementsByClassName(
"step-indicator"
)?.[0]?.offsetHeight;
const minHeight = useMemo(
() => `calc(${heightOfStepper}px + var(--small-spacing))`,
[heightOfStepper]
);
But when I console.log out the heightOfStepper, the value is 0 the first render, and if a add some code to my IntelliJ and save, then I get the real height of the stepper, since then the stepper is already mounted.
How can I get the height of an element after it has rendered, and the component is inside another component? (So I can not just use useEffect(() => ..., []))
In react you should avoid regular DOM queries (like getElementsByClassName) - use ref instead. What do you mean you cannot use useEffect? You can use it even in deeply nested component. If you want to get height of parent element you will want to use forward ref, e.g. like this:
// parent component
const App = () => {
const ref = useRef(null);
return (
<div ref={ref}>
MyDiv
<Child ref={ref} />
</div>
);
};
// child component
const Child = React.forwardRef((props, ref) => {
useEffect(() => {
console.log(ref.current.offsetHeight);
}, []);
return <p>I'm a child component</p>;
});
If your find yourself in need of passing ref deep through components tree or e.g. between siblings - pass ref through context - that was answered here

How to prevent passing className and style props to component in React

Hi I have a custom button component. This button component should accept all ButtonHTMLAttributes except for className and style to prevent devs from adding their own styles. I am using TypeScript with React. How can I achieve this? I tried using Omit but it's not working.
I think what you can do is you can overwrite the styles and classNames properties like:
function CustomButton = (props> => {
return (
<button {...props} className={""} style={{}}/>
)
}
I don't know how you annotated types. But you can try the rest parameter concept.
function Button({className, style, ...restProps}) {
// Use the restProps object
}

React - onChange children component

I'm trying to figure out why onChange wont work on a children component, i have a component named AlertMethod and im calling from a container.
<AlertMethod
onChange={this.methodSelected}
label="Sms"
value="sms"
/>
and methodSelected it's just a console.log() to test if getting called
methodSelected = (event, data) => {
console.log(data);
};
here's an img to explain it better.
so finally that function it wont getting called. that's my problem.
EDIT
On my Container AlertSystem.js i want to update a state if a checkbox it's checked or not, so my checkbox component it's Checkbox.js it's a stateless function, it recive 2 props label and value nothing special. so in my container when my Checkbox Component CHANGED, update my state, so that's why i have a onChange={this.methodSelected} on the children component, because in the methodSelected function ill update my state with this.setState and stuff.
You aren't calling props.onClick in AlertMethod
Your child component AlertMethod is being passed the onSubmit prop but not using it.
Should look more like this:
export const AlertMethod = ({ label, value, onClick }) => {
return (
<div>
<Checkbox value={value} fluid label={label} onClick={onClick} />
</div>
)
}

Understand es6 and jsx in react

I am going through the official redux tutorial.
http://redux.js.org/docs/basics/UsageWithReact.html
In the file
components/Link.js have the following code
import React, { PropTypes } from 'react'
const Link = ({ active, children, onClick }) => {
if (active) {
return <span>{children}</span>
}
return (
<a href="#"
onClick={e => {
e.preventDefault()
onClick()
}}
>
{children}
</a>
)
}
Link.propTypes = {
active: PropTypes.bool.isRequired,
children: PropTypes.node.isRequired,
onClick: PropTypes.func.isRequired
}
export default Link
What I am wondering why function link accepting the variable surrounded by curly braces. Secondly, the return statement inside the if block has the span jsx tag without the braces but the secondly the return statement outside the if block with the <a> tag has a braces. Can anyone explains why?
EDIT: After finding out about destructuring assignment from the answers I read the following article about how to use it in a function and it became very clear to me.
https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/
That's a stateless function, you can define react classes as plain JS functions when they don't have state and life-cycle methods
The curly braces are placed in there to use an amazing es6 feature called Destructuring.
Basically using es6 that's the same as doing:
const Link = (props) => {
const { active, children, onClick } = props;
...
And without using ES6 it would be the same as doing:
const Link = (props) => {
const active = props.active;
const children = props.children;
const onClick = props.onClick;
....
About the return you use brackets when your jsx elements have more then 1 line.
The function argument uses destructuring assignment to extract values from an object.
The braces around JSX are here to keep the indentation clean.
You can do this:
return <div>
lol
</div>
But you can't do this:
return
<div>
lol
</div>
So, to keep the indentation of JSX clean, you have to wrap the markup with braces.

Trouble understanding JSX spread operator [duplicate]

This question already has answers here:
What are these three dots in React doing?
(23 answers)
Closed 1 year ago.
Given this example code from the React docs:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
I did some looking into what ...props actually evaluates to, which is this:
React.__spread({}, props)
Which in turn evaluates to {foo: x, bar: y}.
But what I'm wondering is, why can't I just do this:
var component = <Component props />;
I don't see understand what the point of the spread operator is.
This helps make your code more succinct - since props is an object, the spread operator takes the properties of the object you pass in and applied them to the component. So the Component will have properties a foo with a value of x and a bar with a value of y.
It would be the same as:
var component = <Component foo={props.foo} bar={props.bar} />;
just shorter
One of the best overviews of how object-rest-spread syntax works with react is published at reactpatterns.com:
JSX spread attributes
Spread Attributes is a JSX feature. It's syntactic sugar for passing all of an object's properties as JSX attributes.
These two examples are equivalent.
// props written as attributes
<main className="main" role="main">{children}</main>
// props "spread" from object
<main {...{className: "main", role: "main", children}} />
Use this to forward props to underlying components.
const FancyDiv = props =>
<div className="fancy" {...props} />
Now, I can expect FancyDiv to add the attributes it's concerned with as well as those it's not.
<FancyDiv data-id="my-fancy-div">So Fancy</FancyDiv>
// output: <div className="fancy" data-id="my-fancy-div">So Fancy</div>
Keep in mind that order matters. If props.className is defined, it'll clobber the className defined by FancyDiv
<FancyDiv className="my-fancy-div" />
// output: <div className="my-fancy-div"></div>
We can make FancyDivs className always "win" by placing it after the spread props ({...props}).
// my `className` clobbers your `className`
const FancyDiv = props =>
<div {...props} className="fancy" />
You should handle these types of props gracefully. In this case, I'll merge the author's props.className with the className needed to style my component.
const FancyDiv = ({ className, ...props }) =>
<div
className={["fancy", className].join(' ')}
{...props}
/>
-- quoted from reactpatterns.com by #chantastic
Another good overview was published on the babeljs blog post React on ES6+ by Steven Luscher:
Destructuring & spread attributes
Often when composing components, we might want to pass down most of a parent component’s props to a child component, but not all of them. In combining ES6+ destructuring with JSX spread attributes, this becomes possible without ceremony:
class AutoloadingPostsGrid extends React.Component {
render() {
const {
className,
...others // contains all properties of this.props except for className
} = this.props;
return (
<div className={className}>
<PostsGrid {...others} />
<button onClick={this.handleLoadMoreClick}>Load more</button>
</div>
);
}
}
-- quoted from "BabelJS.org blog - React on ES6+" by Steven Luscher