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.
Related
I have a scenario where I'm a bit confused on how to approach. I feel like there's a lot of refactoring to be done if I were to communicate from the lowest level all the way back up to the parent. I'm very new to using React (a few days now) and I don't know if there's an easier solution to communicate data between components. I've read some sources that said child to parent to other child is best, but I haven't seen mentions of great-great-grandchildren to parent to a child. I've seen mentions about Context API, ComponentDidMount/Update, but I'm not sure what the best approach is.
I'm creating a data explorer on this webpage so we have the RootComponent, LeftPanel, and Graph component.
The LeftPanel holds an Explorer component, which will go through multiple levels of data. On the last level of data, if clicked, it should display a Graph component (through conditional rendering).
ex:
The Parent
export default class RootComponent extends React.Component {
render() {
return (
<div className="flex-row flex-grow">
<LeftPanel />
//Need to conditionally render this
<Graph />
</div>
)
}
}
LeftPanel is a container within the parent that will hold an explorer
export default class LeftPanel extends React.Component {
... (bunch of other logic)
render() {
return (
<Card className="flex-column default-vertical-spacing">
<div className="content">
<Explorer
..........>
</div>
</Card>
)
}
}
Explorer holds data as well as a "Pill" or button to click which will show further levels of data
export default class Explorer extends React.Component<IExplorerProps> {
... (bunch of logic)
render() {
if(!this.props.items || this.props.items.length == 0){
return <span>Loading</span>
}
return (
<ExpandablePill
............../>
)
}
}
ExpandablePill is data that can keep going downward
export default class ExpandablePill extends React.Component<ExpandablePillProps, ExpandablePillState> {
render() {
...
//Here I want to do: If this ExpandablePill was clicked AND it has no children, display a graph.
}
}
This is under the parent RootComponent but I need to know if an ExpandablePill with no levels left was clicked to display a graph (or make it known to the parent-RootComponent that I can display a graph now)
export default class Graph extends React.Component {
render() {
return (
<LineChart
...
</LineChart>
);
}
}
Any suggestions would be appreciated! I apologize if this is a duplicate.
Considering the following three places of defining a functional component in React -
Inside a class (outside the render method)
Inside a class (inside the render method)
Outside the class
In the sample code below, funcComponent1, funcComponent2 and funcComponent3 are defined in the three different locations. How do I consider when to define a functional component in any of these 3 places?
import React, { Component } from 'react';
const FuncComponent1 = (props) => {
return (
<p>{props.name}</p>
)
}
class TestComponent extends Component {
constructor(props){
super(props);
this.state = {
name: "JavaScript"
}
}
FuncComponent2 = (text) => {
return (
<p>{text}, {this.state.name}</p>
)
}
render(){
const FuncComponent3 = (props) => {
return (
<p>{props.text}, {this.state.name}</p>
)
}
return (
<div>
<FuncComponent1 name={'Abrar'} text={'Hello World'}/>
<FuncComponent3 text={"HEllo World"}/>
</div>
)
}
}
export default TestComponent;
You must avoid using functional component inside of render since they will be recreated on every render.
As far as using functions that return JSX inside Class component but outside render` is considered, you can do that when you want to make use of the state or props of the class in order to render JSX content but that which is very specific to the particular class
A functional component outside of React component is most advantageous when the same component can be used at multiple places and hence it makes sense to pass props to it and render it.
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>
)
}
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
I'm studying ReactJS and came across the following component example:
class MyComponent extends React.Component {
constructor(props) {
super(props);
// set the default internal state
this.state = {
clicks: 0
};
this.clickHandler = this.clickHandler.bind(this);
}
componentDidMount() {
this.refs.myComponentDiv.addEventListener(
‘click’,
this.clickHandler
);
}
componentWillUnmount() {
this.refs.myComponentDiv.removeEventListener(
‘click’,
this.clickHandler
);
}
clickHandler() {
this.setState({
clicks: this.clicks + 1
});
}
render() {
let children = this.props.children;
return (
<div className=”my-component” ref=”myComponentDiv”>
<h2>My Component ({this.state.clicks} clicks})</h2>
<h3>{this.props.headerText}</h3>
{children}
</div>
);
}
}
What is the first parameter, 'click', mean in this.refs.myComponentDiv.removeEventListener() and this.refs.myComponentDiv.removeEventListener()? And why do you have to pass in props to super()? And what does the () mean in ({this.state.clicks} clicks})?
Lastly, I came across a stateless component:
const StatelessCmp = (props) => {
return (
<div className=”my-stateless-component”>
{props.name}: {props.birthday}
</div>
);
};
// ---
ReactDOM.render(
<StatelessCmp name=”Art” birthday=”10/01/1980” />,
document.getElementById(“main”)
);
And when do you choose to use a stateless component? And when do you use and what does ReactDOM.render() do, especially the document.getElementById(“main”) portion? Because typically, you would simply do export default ....
And in the following, will simply the two <p>'s be displayed on top of the <MyComponent/> class?
<MyComponent headerText=”A list of paragraph tags”>
<p>First child.</p>
<p>Any other <span>number</span> of children...</p>
</MyComponent>
Thank you and will be sure to upvote and accept answer!
'click' is the name of the click event which is created when you click in the viewport/element
As you are extending the class React.Component you have to pass the properties of your class to the super class (React.Component) that it is correctly instantiated. For more infos read a book about Object oriented programming
I cannot find the statement ({this.state.clicks} clicks}) in your code.
If you do not use this.state use a stateless component
ReactDOM.render() actually creates and renders your components to your page. The document.findElementById('main') is looking for the html element with id="main" that ReactDOM can render it into this element.
I would recommend that you read a basic book or take a online tutorial in javascript first before you learn a js framework like React