styling SVG paths in React - javascript

I am new to React and I'm trying to add an svg image to my component and add dynamic styles to each of its path. However, I am having issues in doing so. I'm using create-react-app
I imported my svg as a React component
import { ReactComponent as SVGimg} from './img/svg-img.svg';
and used it on my render. I was hoping to add styles to all paths by using a for...of loop which I worked on plain HTML/CSS/JS
render() {
const svgImg = document.querySelectorAll('svg path')
for (let path of svgImg) {
path.classList.add('some-class');
}
return(
<div>
<SVGimg/>
</div>
);
}
I also want to mention that the SVG has a lot of paths

You could add a class to the svg say: <svg><path class='pathClass'></svg>
Then in your React component you can get the path by calling: const path = document.getElementsByClassName('pathClass');
And add the class like so: path.classList.add('some-class');
UPDATE
Since you are using a class component you could call the classList.add() method inside the componentDidMont() native React method like so:
class YourComponent extends Component {
constructor(props) {
super(props);
this.svgRef = React.createRef();
}
componentDidMount() {
this.svgRef.current.classList.add('some-class');
}
render() {
return(
<div>
<SVGimg ref={this.svgRef} />
</div>
);
}
}
This will be triggered immediately after the render method finishes.

Related

How to include styles in React create portal

I have ViewAllGraphs class:
import '../styles/Graph.css'
export class ViewAllGraphs extends React.Component {
constructor(props) {
super(props);
this.state = {
showWindowPortal: false,
}
And render method:
return (
<div>
{
this.state.showWindowPortal && (
<Graph closeWindowPortal={this.closeWindowPortal} >
<h1>Id графика : {this.state.currentId}</h1>
<h1>Название графика : {this.state.currentTitle}</h1>
<img o src={`data:image/png;base64,${this.state.currentImage}`} />
<h1>Данные графика : {this.state.currentData}</h1>
<button className="graph-button-close" onClick={() => this.closeWindowPortal()} >
Закрыть график
</button>
</Graph>
)
}
</div>
My CSS file is located in ../styles/Graph.css
I want to style my graph component, for example, the button. This is code of this component:
import React from "react";
import ReactDOM from 'react-dom'
import '../styles/Graph.css'
class Graph extends React.Component {
constructor(props) {
super(props);
this.state = {
id: 0,
}
this.containerEl = null;
this.externalWindow = null;
}
componentDidMount() {
this.externalWindow = window.open('', '');
this.containerEl = this.externalWindow.document.createElement('div');
this.externalWindow.document.body.appendChild(this.containerEl);
this.externalWindow.document.title = 'A React portal window';
this.externalWindow.addEventListener('beforeunload', () => {
this.props.closeWindowPortal();
});
this.shouldComponentUpdate();
this.setState({
id: 1,
})
}
shouldComponentUpdate() {
return true;
}
componentWillUnmount() {
this.externalWindow.close();
}
render() {
if (!this.containerEl) {
return null;
}
else
return ReactDOM.createPortal(this.props.children, this.containerEl);
}
};
export default Graph
I am trying to include the CSS file and apply className="graph-button-close" in render method to my button, but it's not working. Why can't I import the CSS file to graph class?
You can try these code:
this.containerEl = this.externalWindow.document.createElement('div');
this.containerEl.className = 'image';
this.containerEl.style.backgroundImage = 'url(http://via.placeholder.com/350x150)';
// add the image to its container; add both to the body
// this.containerEl.appendChild(img);
this.externalWindow.document.body.appendChild(this.containerEl);
Or for current elem you can use inline styles in parent component
let styleConfig = { backgroundColor: 'blue' }
In render method:
<p style={styleConfig}>Данные графика : {this.state.currentData}</p>
To style a component functionally, and I hope this works for Class Components as well, is that for the styling part of the top of the file, I import the style as a component, something like this,
import componentStyling from '../styles/Graphs.css`;
A bit of advice is that 99% of the time, I want a style to only apply to that component. It's tremendously hard to think of unique class names every single time I make to add styling to a component, so I rename my CSS files with the following format, classComponentName.module.css, or classComponentName.module.scss, if you're using SCSS.
So, whatever the name of the component you're making is, whether it's functional or a class component, name your CSS files with respect to that and then suffix it with .module.css.
Now, the import looks something like this,
import componentStyling from `../styles/Graphs.module.css`;
Now, in the rendering part of the component, wherever I want to apply a class from Graphs.module.css to an HTML component in the component I have, I simply write,
<htmlElement className={componentStyling.classNameFromTheStylesFile}>
{/* some more JSX here */}
</htmlElement>
Where classNameFromTheStylesFile is a class name that exists within Graphs.module.css, which can be for example,
.classNameFromTheStylesFile {
background-color: blue;
};
I hope I got the question right.
Cheers!

Inserting a element into REACT child

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 to create an element and use its ref to append child elements in react?

I'm trying to create a html element on a parent component on react and access that component div inside a child component, then I can append new elements in the div from the child component.
After many attempts I wasn't able to fix props.canvasDivElement.current = null on the child constructor.
I've tried to do this using REF and without refs... No luck so far.
Any ideas?
The parent component looks like:
import React from "react";
import ReactViewer from "../ReactViewer/ReactViewer";
export default class CanvasWrapper extends React.Component {
private _divElement: React.RefObject<HTMLDivElement>;
constructor(props: any) {
super(props);
this._divElement = React.createRef<HTMLDivElement>();
}
render() {
return (
<div>
<ReactViewer canvasDivElement={this._divElement}></ReactViewer>
</div>
);
}
}
The child component:
import React from "react";
type ReactViewerState = {
};
type ReactViewerProps = {
canvasDivElement: React.RefObject<HTMLDivElement>;
};
export default class ReactViewer extends React.Component<ReactViewerProps, ReactViewerState> {
constructor(props: ReactViewerProps, state: ReactViewerState) {
super(props, state);
const newElement = document.createElement('span');
newElement.innerText = 'element';
props.canvasDivElement.current!.appendChild(newElement); //current is null
}
render() {
return (
<div ref={this.props.canvasDivElement} />
);
}
}
Rookie mistake, the element will always be null until it renders.
I've changed the line bellow to the componentDidMount event:
props.canvasDivElement.current!.appendChild(newElement);
It looks like you are trying to circumvent the basic principles of React to solve a problem that React provides other tools for. The React way of communicating between a child and a parent is to pass a callback function to the child. Then the child calls the callback to signal to the parent to update its children.

React - Router inside a element using class

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>
)
}

How to add a class on React component mount?

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

Categories

Resources