How can we assign a class to the outmost wrapper of a component in React?
For example, I was trying to add class "table" to this "FilterableProductTable" so that the outmost wrapper, "" in this case, can have a class assigned to it?
What I did is to add prop "className={"table"}", but it does not seem to work. When inspected, the outmost div still doesn't have a class.
ReactDOM.render(
<FilterableProductTable className={'table'} products={PRODUCTS} />,
document.getElementById("container")
);
the outmost div
the outer wrapper div still doesn't have a class
This is completely possible. You must remember that FilterableProductTable is a Component and doesn't represent a DOM node element, like div, so you are actually just passing a property called className to your Component. It is then up to your component to use the passed in property.
For e.g.
class FilterableProductTable extends Component {
render() {
return (
<div className={this.props.className}>
...
</div>
);
}
}
ReactDOM.render(
<FilterableProductTable className='table' products={PRODUCTS} />,
document.getElementById("container")
);
If you notice above I am actually accessing the passed in property called className via this.props in the FilterableProductTable. So any properties you set on a Component when rendering it will be passed into the Component, and then it is up to the Component's own rendering logic how it wants to use those properties.
You could have called the property foo or whatever too, for e.g.:
class FilterableProductTable extends Component {
render() {
return (
<div className={this.props.foo}>
...
</div>
);
}
}
ReactDOM.render(
<FilterableProductTable foo='table' products={PRODUCTS} />,
document.getElementById("container")
);
Look at the React docs, all the following are HTML Elements natively supported by React:
https://facebook.github.io/react/docs/tags-and-attributes.html#html-elements
If you set the className prop on those items then the class would be attached to them directly. :)
On the outermost div of the FilterableProductTable component you need to include the className prop:
<div className={this.props.className}>
{...children}
</div>
Related
I have read a few questions, and I thought that just setting the id like the following should work:
<MyComponent id="myId"/>
But when I call document.getElementById() on the id, I get null and when I inspect the page, the component has an empty id.
What am I missing?
As #Lekhnath mentioned your MyComponent root elements id can be used to access the component. Something like below where you can access element with "componentId":
class MyComponent extends Component{
render(){
return <div id="componentId">
...your child component details here
</div>
}
}
I have a React component I built for a popup. PopupContent will receive a DOM element or another React component as a child.
class PopupContent extends React.Component {
render() {
return(
<div>
{React.cloneElement(this.props.children, {closePopup:this.props.closePopup})}
</div>
);
}
}
The closePopup prop sets a flag to show/hide the popup
closePopup(event){
event.preventDefault();
this.setState({
popupInView: false
})
}
The reason to pass closePopup to child is to close the popup from the child component.
This setup works well if the child is a custom React component:
<PopupContent>
<ContentOfThePopup />
</PopupContent>
But I get the Unknown Prop Warning if the child is a DOM element.
Warning: React does not recognize the closePopup prop on a DOM
element.
<PopupContent>
<div>Content Of The Popup </div>
</PopupContent>
I could use techniques explained here to distinguish between a DOM element and a React component. But I wanted to check with the community if there is a better way
what does this.props.children contain?
Shouldn't you be iterating over it?
render() {
return React
.Children
// this is the jsx version of cloneElenemnt,
// better to use in a render function
.map(Child => <Child.type ...Child.props ...this.props>)
}
Clone Element
React.Children.map
The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.
You should ensure that you are not accidentally forwarding props that were intended to be interpreted by the parent component.
Also you can try {...this.props} format to pass your data instead of using cloneElement(element, this.props)
I've ended up checking the type of the child and conditionally removing the prop closePopup
Following condition will be true if the child is a HTML DOM element.
typeof this.props.children.type === 'string
My webpage uses React components. At the render function of one of its components div elements that looks like:
<div id='myid'>
{/* ... */}
</div>
are being used. After reloading a page we need to go to one of those divs. For example, after reloading that page we could automatically need to go to the <div> element with id equals to myid. Notice that that <div> is in React virtual DOM so functions like document.getElementById might not work (as it is happening with me). Is this possible?
The <div> and the id will end up in the document when the component is mounted, so you could scroll there in the componentDidMount hook.
Example
class App extends React.Component {
componentDidMount() {
document.getElementById("myid").scrollIntoView();
}
render() {
return (
<div>
<div style={{ height: 1000 }}>Hello CodeSandbox</div>
<div style={{ height: 1000 }} id="myid">
Scroll here
</div>
</div>
);
}
}
You can still get the element using findDOMNode
const div = ReactDOM.findDOMNode(this.refs.mydiv);
Then in the render function
<div ref="mydiv"></div>
And at last
window.scrollTo(0, div.offsetTop);
If the element is rendered by react you should use a ref to get the element to call scrollIntoView() on it:
class MyComponent extends Component {
ref = elem => elem.scrollIntoView();
render() {
return (
<div ref={this.ref}>{/* ... */}</div>
);
}
}
Using getElementById() or React.findDOMNode may also work but there you have the problem that you need to know if the component already mounted. If you do the scrolling inside the component (which is recommended) using a ref is the best solution.
I would like to know if there is a way to only render a parent component when its child is rendered and vis versa. If you google the title you find quite a few entries but nothing the would work for my case because my elements aren't undefined or null, for example. Imagine a Parent:
class Parent extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<div>
<div className="container">
{this.props.children}
</div>
</div>
);
}
}
The following child might be depended on some settings. For instance, only show if a boolean is true.
class Child extends React.Component {
constructor(props){
super(props);
const showChild = Settings.get(...);
this.state = {
visible:showChild
}
}
render() {
const showHello = this.state.visible ? <div>Hello</div> : "";
return (
<div>{showHello}</div>
);
}
}
In my layout I scaffold it like this:
class Layout extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<Parent>
<Child />
</Parent>
);
}
}
Is it possible to unmount Parent if that Child element is not rendered? Thank you.
Update: A use case is if I want this Parent and Child to be in a Layout and Parent has a container class with a larger padding or margin because it is still in the component tree. If Child isn't rendered a large gap remains within the Layout and it just looks odd.
React was not designed with this workflow in mind, in fact the opposite: data is explicitly passed down the DOM tree, while actions are passed upward. By extension, React must render your Parent before your Child.
I'd suggest refactoring your Parent and Child to the point where Parent is aware of which settings its Child needs; insofar as your Child component is engaged with:
<Child settings={settings} />
To reiterate, this is also a more natural approach to React, whereby data is explicitly passed downward, and not implicitly loaded in the Child (although there's always exceptions, like the ability of connect() components with react-redux). But a benefit to this approach is that now Parent is able to determine whether or not to render its Child.
But what about the rendering of Parent? Don't we want to inhibit that too? If you do, then you'll need your Layout component to be aware of what it's Parent component needs, therefore:
<Parent settings={settings} />
This is a common approach to React since rendering down the DOM hierarchy is a must.
You could conditionally render in your Parent component by checking to see if it has any children.
Use this.props.children.length to see if there are any, if yes, render normally, if not return an empty element.
I have a React component called <SensorList /> that has many child <SensorItem />s (another React component). I want to be able to declare an onClick event on each <SensorItem /> from within <SensorList />. I have tried doing the following:
sensorSelected: function(sensor) {
console.log('Clicked!');
},
render: function() {
var nodes = this.state.sensors.map(function(sensor) {
return (
<SensorItem onClick={ this.sensorSelected } />
);
}.bind(this));
return (
<div className="sensor-list">
{ nodes }
</div>
);
}
Needless to say, I do not get any "Clicked!" coming up in my console. The React inspector in Chrome indicates that an onClick event is registered, with the above function body as it should be.
I conclude, therefore, that I can't register onClick events on the actual <SensorItem /> tags (I'm not sure why this is, however). How do I go about achieving this otherwise?
This depends on your SensorItem component's definition.
Because SensorItem isn't a native DOM element but, like you said, another React component, onClick as defined here is simply a property of that component. What you need to do is, inside of the SensorItem component pass the onClick prop to an DOM component's onClick event:
var SensorItem = React.createClass({
render: function() {
return (
<div className="SensorItem" onClick={this.props.onClick}>
...
</div>
);
}
});
Problem
The problem, as being explained in another answer, is that onClick on a <SensorItem> React component (contrary to native DOM element like <div> or <p>) is treated as passing of component property, and not of a DOM event handler. And as most likely your <SensorItem> component doesn't declare onClick property, that property value simply gets lost.
Solution
The most straightforward solution is to add onClick property explicitly on SensorItem component, then pass it to the root DOM element of that component:
function SensorItem({ prop1, prop2, onClick }) {
(...)
return (
<p onClick={onClick}>
(...)
</p>
);
}
But the solution that usually works best for me is to group all the undefined component's properties using object destructuring notation, then pass them all to the root DOM element within that component. This way you can pass onClick, onHover, className etc. without needing to define separate properties for each one of them:
function SensorItem({ prop1, prop2, ...rootDOMAttributes }) {
(...)
return (
<p {...rootDOMAttributes}>
(...)
</p>
);
}
No matter which of the two approaches you use, the handler will now work, as it'll now be attached to the root DOM element of SensorItem:
<SensorItem onClick={...} />