My React app has a base div like so:
<body>
<div id="root">
....
</div>
</body>
In my Welcome container, I would like to add a class to the div w id="root and then on Welcome container unmount, remove the class.
class Welcome extends React.Component {
componentDidMount() {
console.log('componentDidMount');
console.log($('#root'));
}
....
With jQuery I could do something like
$('#root').addClass('myClass')
....
$('#root').removeClass('myClass')
What is the equivalent in React for adding and removing a class on a div after finding it by its ID?
This makes no sense. You shouldn't be adding classes to root from React components. The root div should just exist to inject React in to using ReactDOM.
Instead of modifying the html root, create a react class called App or something and render a <div className="app" /> that wraps all of your components. You can then use React state or props to modify the className.
class App extends React.Component {
constructor() {
super();
this.state = {
appClass: 'myClass'
};
}
componentDidMount() {
this.setState({ appClass: 'newClass' });
}
render() {
return (
<div className={this.state.appClass}>
// Render children here
</div>
);
}
}
If you want to modify the appClass from a child component such as Welcome which is further down in your application then you will need to use a state management like Redux or Flux to modify the className from a child component otherwise it will get messy fast.
EDIT: removed semicolon from this.state object
Related
I am rendering a chart with react, and I would like to add an element to the title of that chart. Unfortunately, I am using a shared chart component, and majorly modifying the component would be difficult to justify.
I have tried using refs; however, I'm running into difficulty figuring how to actually append a virtual dom element as a child element.
Specific Chart Class:
class ChartWithInfo extends React.Component {
constructor(props){
super(props);
this.chartWrapperElement = React.createRef();
}
componentDidMount() {
const infoInsertion = (
<div>
<IconButton/>
</div>
)
this.chartWrapperElement.current.insertBefore(infoInsertion, this.chartWrapperElement.current.firstChild);
}
render() {
return (
<GenericChart
variables={this.props.variables}
ref={this.chartWrapperElement}
/>
);
}
}
Generic Chart Class
export default class EmbeddedChart extends PureComponent {
// Random methods //
render() {
return (
<div ref={this.props.ref} id={'chartDiv'}>
Chart
</div>
);
}
}
The expected result would essentially be:
<div id='chartDiv'>
<IconButton/>
</div>
What is the most react way to do this? Am I missing something with refs?
React is meant for components and if you follow the separation of concern and component architecture. You can segregate all your components and individual reusable components. Create your button component separately and import anywhere else. Bind your events and business logic respectively.
How do i render a react component using class?
I have the following code:
class PageLogin extends React.Component {
render() {
return (<p>hello</p>)
}
}
export default PageLogin
When i import it, it render the component entirely, updating the page, so how do i inject it into a div in the component that is rendered?
Ah okay, I think I see what you mean. By default, you can't specify where an individual component is rendered. You tell your main component to render in <div id="id"></div>, so that means EVERY component will use that div as the render root.
However, as of React v16 you can use ReactDOM.createPortal to render a component in any element.
class PageLogin extends React.Component {
render() {
return (
<div>
{ReactDOM.createPortal(<p>hello</p>, document.getElementById('anotherRoot'))}
</div>
)
}
}
export default PageLogin
Ideally though, you'd want to move that code to wherever you are rendering PageLogin:
render() {
return (
<div>
{ReactDOM.createPortal(<PageLogin />, document.getElementById('anotherRoot'))}
</div>
)
}
I have custom component in my reactjs application:
class Word extends React.Component {
click() {
// can i access app instance here?
}
}
Your question is not precise but I am assuming you have top level App component which has child components and you are asking if child component can access App component.
If thats the case then just pass reference to it as a prop:
class App extends React.Component {
render() {
<Word parent={this} />
}
}
class Word extends React.Component {
click() {
console.log(props.parent);
}
}
However I believe this to be anti-pattern.
I have a file named separatefile.jsx, in this file parent component name is Content and child component name is Child.
separatefile.jsx
import React from 'react';
import Parent from './learning.jsx';
class Content extends React.Component {
constructor() {
super();
this.state = {
finding : 'i am finding'
}
}
render() {
return (
<div>
<Child childprop={this.state.finding}/>
<Parent/>
</div>
);
}
}
class Child extends React.Component {
render() {
return (
<div>
<h2>{this.props.childprop}</h2>
<h1>child class property</h1>
</div>
);
}
}
export default Content;
This is another file named as learning.jsx , this file has Parent component named as Parent and Child component named as a Children.
My questions is that i need to access Parent component property(parent component for learning.jsx) from Child component(child component for separatefile.jsx file)...
learning.jsx
import React from 'react';
class Parent extends React.Component {
constructor() {
super();
this.state = {
searching : 'i will find the solution'
}
}
render() {
return (
<div>
<Children childrenprop={this.state.searching}/>
</div>
);
}
}
class Children extends React.Component {
render() {
return (
<div>
<h2>{this.props.childrenprop}</h2>
</div>
);
}
}
export default Parent;
If I understood you correctly, you want to use Parent's state in your Children component?
You can pass it down the component tree as props, e.g.:
class Content extends React.Component {
constructor() {
super();
this.state = {
finding : 'i am finding'
}
}
render() {
return (
<div>
<Child childprop={this.state.finding}/>
<Parent finding={this.state.finding} />
</div>
);
}
}
class Parent extends React.Component {
constructor() {
super();
this.state = {
searching : 'i will find the solution'
}
}
render() {
return (
<div>
<Children finding={this.props.finding} childrenprop={this.state.searching}/>
</div>
);
}
}
class Children extends React.Component {
render() {
return (
<div>
<h2>{this.props.childrenprop}</h2>
<div>{this.props.finding}</div>
</div>
);
}
}
It's probably not a direct answer but if you are starting a new app I would recommend you to use Redux with react-redux.
Redux is a predictable state container for JavaScript apps.
It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as live code editing combined with a time traveling debugger.
It's very small library so it's easy to understand how everything works. It might be a good solution to your problem.
Todo app example
You can also check out awesome egghead.io free tutorial - Getting Started with Redux
Here is the answer about the redux benefits by its author Dan Abramov
The React documentation provides an answer.
For communication between two components that don't have a
parent-child relationship, you can set up your own global event
system. Subscribe to events in componentDidMount(), unsubscribe in
componentWillUnmount(), and call setState() when you receive an event.
Flux pattern is one of the possible ways to arrange this.
I have a react component that wraps another, and sets the child's onClick like this:
class OutstandingActionForm extends Component {
render() {
return (
<div className="outstanding-actions">
{React.cloneElement(this.props.children, {onClick : this.openForm})}
It basically lets the parent (OutstandingActionForm) open a modal if the child (whatever it is) is clicked, and separates the appearance of the click-target from the behaviour of the thing that opens.
This works fine if the child is an <img>:
<OutstandingActionForm actions={this.props.actions}>
<img src={'/assets/notification.jpg'} className="notification-icon"/>
</OutstandingActionForm>
In this case, the OutstandingActionForm opens if the notification.jpg <img> is clicked.
However, for some reason it doesn't work if the child component is itself a react component:
<OutstandingActionForm actions={this.props.actions}>
<OutstandingActionsSummary/>
</OutstandingActionForm>
Even if OustandingActionSummary is itself just an image:
class OutstandingActionsSummary extends Component {
render() {
return (
<img src={'/assets/notification.jpg'} className="notification-icon"/>
)
}
Why is this so? How could I achieve the same when wrapping a react component as when wrapping the native <img> tag?
<img> knows how to use onClick. But <OutstandingActionsSummary> doesn't! In the implementation of <OutstandingActionsSummary>, you have to specify how to use the property. It should look like:
class OutstandingActionsSummary extends Component {
render() {
return <img onClick={this.props.onClick}/>
}
class OutstandingActionsSummary extends Component {
static defaultProps ={
onClick:function(){}
}
render() {
return (
<img onClick={()=>this.props.onClick()} src={'/assets/notification.jpg'} className="notification-icon"/>
)
}
OutstandingActionsSummary doesnot support onClick,add it.
In OutstandingActionForm use only {this.props.children} and attach click handler on OutstandingActionsSummary and call its parent OutstandingActionForm to process.