Importing svg path from another component using react.js - reactjs

I have multiple icons stored in a component under switch statement. Based on a condition, I want to display that icon in render function of another component. If I manually add the svg and the path element, then the icon gets displayed correctly. But I would like to optimize my code such that when I call the function with correct parameters, it extracts the corresponding svg element along with its path element.
First Component(where icons reside):
export function getSymbolPlotly(symbol) { // eslint-disable-line
let elm;
const { color, shape } = symbol;
switch (shape) {
case 'x-dot':
elm = <path
className="point"
transform="translate(8,8)"
d="M0,3.39l3.39,3.39l3.39,-3.39l-3.39,-3.39l3.39,-3.39l-3.39,-3.39l-3.39,3.39l-3.39,-3.39l-3.39,3.39l3.39,3.39l-3.39,3.39l3.39,3.39ZM0,0.5L0.5,0L0,-0.5L-0.5,0Z"
style={{
opacity: 1,
strokeWidth: '0px',
fill: color,
fillOpacity: 1
}}></path>;
break;
case 'square':
elm = <path
className="point"
transform="translate(8,8)"
d="M6,6H-6V-6H6Z"
style={{
opacity: 1,
strokeWidth: '0px',
fill: color,
fillOpacity: 1
}}></path>;
break;
case 'hourglass':
elm = <path
className="point"
transform="translate(6,8)"
d="M6,6H-6L6,-6H-6Z"
style={{
opacity: 1,
strokeWidth: '0px',
fill: color,
fillOpacity: 1
}}></path>;
break;
default:
elm = <circle cx="6" cy="6" r="6" transform="translate(0,2)" fill={color}></circle>;
}````
Second component(render function where I need to display icons):
````switch (user.processState) {
case 'DENIED':
return <span><svg style={{ width: '15px', height: '15px' }}>
{getSymbolPlotly('hourglass')}
</svg></span>
case 'CANCELLED':
return <span><svg style={{ width: '15px', height: '15px' }}>
<path className="point"
transform="translate(8,8)"
d="M0,3.39l3.39,3.39l3.39,-3.39l-3.39,-3.39l3.39,-3.39l-3.39,-3.39l-3.39,3.39l-3.39,-3.39l-3.39,3.39l3.39,3.39l-3.39,3.39l3.39,3.39ZM0,0.5L0.5,0L0,-0.5L-0.5,0Z"
style={{
opacity: 1,
strokeWidth: '0px',
fill: '#e5004c',
fillOpacity: 1
}}></path>
</svg>{this.state.message}</span>;
}
In the above code, case CANCELLED displays the icon perfectly as I am manually adding the path element. But I would like to optimize the code as I would need to display the icons at multiple locations and adding path element at every position would make the code tedious. If I call the getSymbol function and pass the name of the icon as parameter, it doesn't display anything. Even when the parameter doesn't match any case, it won't even display the default circle element.
Is there a way to extract the svg and path element in cleaner way from another component ?

In your getSymbolPlotly function you destructure an object called symbol const { color, shape } = symbol;. When you call that function you pass a string called getSymbolPlotly('hourglass'), there is the first error.
I don't know if you pasted the entire code for the getSymbolPlotly function but you must also return the element. To extract in a more "clean" way you can to like this.
import React from "react";
export function getSymbolPlotly(symbol) {
// eslint-disable-line
const { color, shape } = symbol;
switch (shape) {
case "x-dot":
return (
<path
className="point"
transform="translate(8,8)"
d="M0,3.39l3.39,3.39l3.39,-3.39l-3.39,-3.39l3.39,-3.39l-3.39,-3.39l-3.39,3.39l-3.39,-3.39l-3.39,3.39l3.39,3.39l-3.39,3.39l3.39,3.39ZM0,0.5L0.5,0L0,-0.5L-0.5,0Z"
style={{
opacity: 1,
strokeWidth: "0px",
fill: color,
fillOpacity: 1
}}
/>
);
case "square":
return (
<path
className="point"
transform="translate(8,8)"
d="M6,6H-6V-6H6Z"
style={{
opacity: 1,
strokeWidth: "0px",
fill: color,
fillOpacity: 1
}}
/>
);
case "hourglass":
return (
<path
className="point"
transform="translate(6,8)"
d="M6,6H-6L6,-6H-6Z"
style={{
opacity: 1,
strokeWidth: "0px",
fill: color,
fillOpacity: 1
}}
/>
);
default:
return (
<circle cx="6" cy="6" r="6" transform="translate(0,2)" fill={color} />
);
}
}
And in some other component you can call it like this.
return (
<div className="App">
<div>
<svg style={{ width: "15px", height: "15px" }}>
{getSymbolPlotly({ shape: "hourglass", color: "red" })}
</svg>
</div>
<div>
<svg style={{ width: "15px", height: "15px" }}>
{getSymbolPlotly({ shape: "x-dot", color: "purple" })}
</svg>
</div>
</div>
);
I've created a Codesandbox with a working demo here.

Related

How to change the image size in a reusable component?

In my React Native application, I have a 48 x 48 profile picture component that is in the header on all of the screens.
ProfilePicture.jsx
const ProfilePicture = () => {
return (
<>
<Image style={styles.profPic} source={{ uri: userObj?.avatar }} />
</>
);
};
const styles = StyleSheet.create({
profPic: {
minHeight: 48,
minWidth: 48,
borderRadius: 100,
shadowColor: "#000",
shadowOffset: {
width: 2,
height: 2,
},
shadowOpacity: 1.0,
shadowRadius: 3.84,
elevation: 5,
},
});
export default ProfilePicture;
Now, I want to use a larger version in my user settings screen where the user can change their profile image.
My thought was that by setting the style in the imported component, it would show a larger version of the image:
<ProfilePicture style={{ width: 100, height: 100 }} />
However, the image remains the same size. I know I could just create another component with the required size for this page, but since the image comes from a remote server, I don't want to call the URL multiple times.
How can I do this just using my current component?
A good way to handle this would be to pass in a style prop to your ProfilePicture component. That way any component using the ProfilePicture component would be able to overrule the default styling. Combine this with the fact that the style prop of react-native components can take in arrays as value, and the code is pretty clean
const ProfilePicture = ({ style }) => {
return (
<Image style={[styles.profPic, style]} source={{ uri: userObj?.avatar }} />
);
};
const styles = StyleSheet.create({
profPic: {
minHeight: 48,
minWidth: 48,
borderRadius: 100,
shadowColor: "#000",
shadowOffset: {
width: 2,
height: 2,
},
shadowOpacity: 1.0,
shadowRadius: 3.84,
elevation: 5,
},
});
export default ProfilePicture;
Your example code will then work as intended
<ProfilePicture style={{ width: 100, height: 100 }} />

is it possible to animate a strikethrough with React Spring?

I'm new to React Spring and I initially tried this
const strikeProps = useSpring({
textDecoration: "line-through",
from: { textDecoration: "none" },
});
But it's not working. I think there should be a way simulate the CSS solution for this.
The problem here is, that the original CSS solution is uses pseudo element for emulating the strike trough. We can only add react-spring properties for normal html elements. So the most compact way is to create a separate strike through component for this problem. For example:
const StrikeTroughtText = ({ children, weight = 1 }) => {
const props = useSpring({
from: { width: "0%" },
to: { width: "100%" }
});
return (
<div style={{ position: "relative", display: "inline-block" }}>
{children}
<animated.div
style={{
position: "absolute",
top: "50%",
left: 0,
width: props.width,
height: `${weight}px`,
background: "black"
}}
/>
</div>
);
};
We basically animate the width of the absolutely positioned div containing a black line over the text.
You can use it like a div component:
<StrikeTroughtText>text</StrikeTroughtText>
For bigger font size the default 1 px line weight is not enough, so I added a weight property also.
Here is my example: https://codesandbox.io/s/react-strike-trought-text-component-with-react-spring-animation-86cfd?file=/src/App.js

How to create shadow inside TextInput REACT-NATIVE

I need to create the same view of TextInput like on photo. Any ideas?
link to photo:
Try using react-native-linear-gradient. i.e.
<LinearGradient
style={styles.container}
locations={[0, 0.15, 0.15]}
colors={['rgba(200, 200, 218, 0.25)', 'rgba(200, 200, 218, 0.005)', '#eafcff']}
>
<TextInput
{/* ... */}
/>
</LinearGradient>
// ....
const styles = StyleSheet.create({
container: {
//...
backgroundColor: '#eafcff',
},
//...
How about this inset property ?
box-shadow: inset 0 0 5px 5px #888;

Can't change body height reactJS

I'm discovering ReactJS, trying some stuff but i face a problem: my body height is fixed to 76px and i can't do anything to that, i tried a lot a stuff, nothing worked.
Here's the code i'm using
import * as React from 'react';
// This fonction make the color change on the button on the first click
function ChangeStyle() {
var elem = document.getElementById('Button1');
if (elem == null) {
return;
}
elem.style.background = '#ff4848';
}
// Main Class
export class Button extends React.Component {
render() {
// Style sheet of the Button
var buttonStyle = {
fontSize: 50,
background: '#ffb516',
color : '#FFFFFF',
width: 500,
border: 'none',
textAlign: 'center',
display: 'block',
margin: 'auto'
};
// Set the Background color
document.body.style.backgroundColor = '#25353f';
document.body.style.position = 'relative';
document.body.style.height = '100%';
// Try to make the button in center
/*
var centerDiv = {
position: 'absolute' as 'absolute',
top: '50%',
left: '30%',
margin: 'auto'
}
*/
// Test on linearGradient
/*
function degraded() {
<svg width='15' height='71' fill='url(#Gradient-1)'>
<defs>
<linearGradient id='Gradient-1' x2='0%' y2='100%'>
<stop offset='0%' stop-color='#25353f'/>
<stop offset='100%' stop-color='#5b6c72'/>
</linearGradient>
</defs>
</svg>
}
*/
// Create the button
return (
<div id="fullHeight" style={{height: '100%'}}>
<div /*style={centerDiv}*/>
<button
id="Button1"
style={buttonStyle}
onClick={() => ChangeStyle()}
>
Pushtalents
</button>
</div>
</div>
);
}
}
export default Button;
Any idea why? And how to fix this problem?
Maybe it helps if you remove position: relative; from body. It doesn't do anything anyways. Other than that you can try to set the body height to 100vh.

What is MobileTearSheet and where is it?

What is MobileTearSheet and where is it?
By all means copy the one from the docs site. (it's just an image.)
Take it:
https://raw.githubusercontent.com/callemall/material-ui/master/docs/src/app/components/MobileTearSheet.js
Here is my working version (in one file) you can drop into you project.
If you want to use this source, please up vote this answer
MobileTearSheet.js
import React, from 'react';
const MobileTearSheet = React.createClass({
getDefaultProps() {
return { height: "100%" }
},
render:function() {
const styles = {
root: {
marginBottom: 24,
marginRight: 24,
maxWidth: 360,
width: '100%',
},
container: {
border: 'solid 1px #d9d9d9',
borderBottom: 'none',
height: this.props.height,
overflow: 'hidden',
},
bottomTear: {
display: 'block',
position: 'relative',
marginTop: -10,
maxWidth: 360,
},
};
return (
<div style={Object.assign({},styles.root,this.props.style||{})}>
<div style={styles.container}>
{this.props.children}
</div>
<div style={styles.bottomTear}>
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" viewBox="0 0 360 10" enableBackground="new 0 0 360 10">
<polygon fill="#DAD9D9" points={`359,0 359,7.5 352.5,0.5 345,8.5 337.5,0.5 330,8.5 322.5,0.5 315,8.5 307.5,0.5 300,8.5 292.5,0.5
285,8.5 277.5,0.5 270,8.5 262.5,0.5 255,8.5 247.5,0.5 240,8.5 232.5,0.5 225,8.5 217.5,0.5 210,8.5 202.5,0.5 195,8.5 187.5,0.5
180,8.5 172.5,0.5 165,8.5 157.5,0.5 150,8.5 142.5,0.5 135,8.5 127.5,0.5 120,8.5 112.5,0.5 105,8.5 97.5,0.5 90,8.5 82.5,0.5
75,8.5 67.5,0.5 60,8.5 52.5,0.5 45,8.5 37.5,0.5 30,8.5 22.5,0.5 15,8.5 7.5,0.5 1,7.5 1,0 0,0 0,10 7.5,2 15,10 22.5,2 30,10
37.5,2 45,10 52.5,2 60,10 67.5,2 75,10 82.5,2 90,10 97.5,2 105,10 112.5,2 120,10 127.5,2 135,10 142.5,2 150,10 157.5,2 165,10
172.5,2 180,10 187.5,2 195,10 202.5,2 210,10 217.5,2 225,10 232.5,2 240,10 247.5,2 255,10 262.5,2 270,10 277.5,2 285,10
292.5,2 300,10 307.5,2 315,10 322.5,2 330,10 337.5,2 345,10 352.5,2 360,10 360,0 `}/>
</svg>
</div>
</div>
);
}
})
export default MobileTearSheet;
For usage see: material-ui list example
I found this question while debugging why the List example code wasn't compiling. Don't worry you can just replace the tags with a and it should work just fine!

Resources