React Pie chart with range slider without using state - reactjs

I want to draw pie chart in react .
when slider range changes the pie chart should change according to value of range slider.
We cant use state in the assignment.
problem is that i am new in react and dont know how to change child attribute (stroke-dasharray in my case) value from parent without using state which should be reflected on pie chart.
any one please help me .
my whole code is below.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Raect Aiignment - PI Chart</title>
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.js"></script> -->
<script src="https://unpkg.com/chart.js#2.7.2/dist/Chart.bundle.js"></script>
<!-- chartkick dependency on chart.js -->
<script src="https://unpkg.com/react-chartkick#0.3.0"></script>
<style>
.circle_style
{
fill: #f4fc16;
stroke: #DF5C24;
transition: stroke-dasharray 1s linear infinite
}
.svg_style {
background: #f4fc16;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const svgVars = {
svgWidth: 100,
svgHeight: 100,
defaultRadius: 25,
cX: 50,
cY: 50,
defaultStrokeWidth: 50, // 2*circleRadius = 50
};
const circumferenceWidth = () => Math.PI * 2 * svgVars.defaultRadius;
var dashWidth = (rangeSliderValue = 50) => {
return ( rangeSliderValue * circumferenceWidth() / 100).toFixed(3) ;
};
class Slider extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<form id="slider_form" role="form">
<input type="range" min={0} max={100} defaultValue={25} step={1} onChange={this.props.doAfterSlide} />
</form>
);
}
}
class Head extends React.Component {
render() {
return (
<h1>PI Chart with range slider</h1>
);
}
}
class Chart extends React.Component {
render() {
let cirStyle = {
strokeDasharray: `${ dashWidth() } ${ circumferenceWidth() }`,
strokeWidth: svgVars.defaultStrokeWidth
}
return (
<svg width={ svgVars.svgWidth } height={ svgVars.svgHeight } className="svg_style">
<circle r={ svgVars.defaultRadius } cx={ svgVars.cX } cy={ svgVars.cY } style={ cirStyle } className="circle_style" />
</svg>
);
}
}
class PieChart extends React.Component {
constructor(props) {
super(props);
// This binding is necessary to make `this` work in the callback
this.updatePiechart = this.updatePiechart.bind(this);
}
updatePiechart(e) {
let sliderValue = e.target.value;
let dw = dashWidth(sliderValue);
console.log(dw);
console.log("hello");
}
render() {
return (
<div>
<Head />
<Slider doAfterSlide={this.updatePiechart} />
<Chart />
</div>
);
}
}
/**
* Render
*
*/
ReactDOM.render(
<PieChart />,
document.getElementById('root')
);
</script>
</body>
</html>

You could store the new dashWidth value in a global variable or property of the PieChart class, and pass this value to Chart through props.
Then call this.forceUpdate() to cause the PieChart to re-render when it changes.
Note, I would never do this in real code, instead I would use state, since this is exactly what state is meant to be used for. Not allowing the use of state is a really strange constraint for a assignment using React.

Related

How to pass a json array in react?

First of all I want to clear this I am using cdn for react and using ajax for fetching the details from the json file.
So,I have a json file reactjs.json which looks like...
[
{
"e64fl7exv74vi4e99244cec26f4de1f":[ "image_1.jpg","image_2.jpg"]
}
]
index.html
<!DOCTYPE html>
<html>
<head>
<title>Image Viewer-Static</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/babel">
class FetchDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentDidMount() {
axios.get('reactjs.json').then(res => {
console.log(res.data);
this.setState({ images: res.data });
});
}
render() {
const { images } = this.state;
return (
<div>
{this.state.images.map((images, index) => (
<PicturesList key={index} apikeys={images.e64fl7exv74vi4e99244cec26f4de1f} />
))}
</div>
);
}
}
class PicturesList extends React.Component {
render() {
return (
<img src={this.props.apikeys} alt={this.props.apikeys}/>
);
}
}
ReactDOM.render(
<FetchDemo/>,
document.getElementById("root")
);
</script>
</body>
</html>
I want to show the image named image_1.jpg,image_2.jpg but this.props.apikeys fetch the value like image_1.jpg,image_2.jpg
images
But I want that it gives two values and show the two image.
I tried a lot to solve this but fails.Any suggestion and help will be welcomed.
Here you are setting the array [ "image_1.jpg","image_2.jpg"] to apiKeys in
<PicturesList key={index} apikeys={images.e64fl7exv74vi4e99244cec26f4de1f} />
So when you try to set the image src here
<img src={this.props.apikeys} alt={this.props.apikeys}/>
what you are setting as this.props.apikeys to src is an array. You have to handle the two images in the array separately to set the source of each image as a String. Try as follows.
{this.props.apikeys.map((image, index) => (
<img src={image} alt={image}/>
))}
since you already have the json file in the file structure you can just import and use it..
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import reactjsJSON from "./reactjs.json";
class FetchDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
images: reactjsJSON
};
}
** Edit: **
Your html file
<!DOCTYPE html>
<html>
<head>
<title>Image Viewer-Static</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/babel">
class FetchDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentDidMount() {
axios.get('/reactjs.json').then(res => {
console.log(res.data);
this.setState({ images: res.data });
});
}
render() {
const { images } = this.state;
return (
<div>
{ this.state.images.map(imageObjs =>
Object.keys(imageObjs).map(key =>
imageObjs[key].map((image, index) => (
<PicturesList key={index} apikeys={image} />
))
)
)}
</div>
);
}
}
class PicturesList extends React.Component {
render() {
console.log(this.props)
return (
<img src={this.props.apikeys} alt={this.props.apikeys}/>
);
}
}
ReactDOM.render(
<FetchDemo/>,
document.getElementById("root")
);
</script>
</body>
</html>
Your JSON, tested for all possibilities, replaced with dummy images
[
{
"e64fl7exv74vi4e99244cec26f4de1f": [
"https://picsum.photos/200?image=2",
"https://picsum.photos/200?image=2"
],
"e64fl7exv74vi4e99244cec26f4deop": [
"https://picsum.photos/200?image=2",
"https://picsum.photos/200?image=2"
]
},
{
"e64fl7exv74vi4e99244cec26f4de1g": [
"https://picsum.photos/200?image=2",
"https://picsum.photos/200?image=2"
]
}
]
serve both the files in same http server and check the output.... since both files are served from same server u can add './' path to fetch and get JSON data...
Looks to me like you are receiving this JSON repose & then setting a JSON object into your state. Try looking at
JSON.parse()
. Your also setting the whole JSON object to your images array. You need select a key.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
I write a demo in codesandbox: https://codesandbox.io/s/oorn5o162q, you can check it out.
I use two real image urls in json, and refine your component code.

Very ReactJS with PHP

Hi I have started to learn React JS but when I'm Starting to fetch API I'm getting an error:
parsing failed SyntaxError: Unexpected end of input
This is my source code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<style type="text/css">
body {
background: #538cb5;
}
.app-container {
background: #fff;
max-width: 480px;
margin: 60px auto;
padding: 40px 25px;
}
h3 {
color: #538cb5;
}
input {
margin: 20px 0;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js' crossorigin></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js" crossorigin></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js" crossorigin></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js" crossorigin></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
render() {
return <Data />
}
}
class Data extends React.Component {
constructor(props) {
super(props)
this.state = {
data : [
{"play_slot_id":"227","playSlot":"E","date":"2018-10-06","time":"14:00","randValue":"683394","new_randValue":"","createdDate":"2018-10-06 13:26:30","updatedDate":"2018-10-06 13:26:30","status":"active"},{"play_slot_id":"227","playSlot":"E","date":"2018-10-06","time":"14:00","randValue":"683394","new_randValue":"","createdDate":"2018-10-06 13:26:30","updatedDate":"2018-10-06 13:26:30","status":"active"},{"play_slot_id":"227","playSlot":"E","date":"2018-10-06","time":"14:00","randValue":"683394","new_randValue":"","createdDate":"2018-10-06 13:26:30","updatedDate":"2018-10-06 13:26:30","status":"active"}
]
}
}
componentDidMount(){
fetch('http://iqexpert.in/android_login_api/getRand.php',{mode: 'no-cors'})
.then((res) => {
console.log(res)
return res.json()
})
.then((data) => {
console.log('parsed json', data)
this.setState({data : data})
})
.catch(function(ex) {
console.log('parsing failed', ex)
})
}
render(){
if(!this.state.data) return <p>Loading</p>
var elements = this.state.data.map( (item,index) => {
return <li key={item.id}>SLOT: {item.playSlot} | Random: {item.randValue} </li>
})
console.log(elements)
return <ol>{elements}</ol>
}
}
ReactDOM.render(<App />, document.getElementById("root"))
</script>
</body>
</html>
I tried with and without CDN but still getting the same errors in ReactJS. I have made API's for my Android Project. It is consumed properly in Android devices but I am not able to render properly in React JS.
I am not sure how we should implement React components between script tags, but don`t you need to import React as import React from 'react'
<script type=text/babel>
import React from 'react' // <<---- HERE
class App extends React.Component {

onMouseMove doesnot work outside of element react

I have an svg element on which I am doing onMouseDown, OnMouseMove and onMouseUp. My problem is that as soon as the user leaves the element while still holding their mouse button down, it does not register the mousemove.
I want to keep the onMouseMove event on even after user leaves the element.
Here is my code:
Class School extents React.Component {
onDragStartCircle = (e) {
//taking the initial state
}
onDragCircle = () {
// draging the element
}
onDragEndCircle = () {
// saving data to the database
}
render() {
return (
<div>
<svg>
<circle
cx={50}
cy={50}
r={10}
fill="red"
onMouseDown={this.onDragStartCircle}
onMouseMove={this.onDragCircle}
onMouseUp={this.onDragEndCircle}
/>
</svg>
</div>
);
}
}
I have also tried onDragStart, onDrag these are not working. I am using es6.
Here is an example of your code, whichs shows how to use a container to register events outside of that circle.
You should consider subscribing to the move event on drag start, and unsubscribing again on drag end, to prevent to much events firing. But this should get you started.
class School extends React.Component {
onDragStartCircle = (e) => {
console.log('drag start')
}
onDragCircle = () => {
console.log('move')
}
onDragEndCircle = () => {
console.log('drag end')
}
render() {
return (
<div class="container"
onMouseMove={this.onDragCircle}
onMouseUp={this.onDragEndCircle}>
<svg>
<circle
cx={50}
cy={50}
r={10}
fill="red"
onMouseDown={this.onDragStartCircle}
/>
</svg>
</div>
);
}
}
ReactDOM.render(
<School />,
document.getElementById("react")
);
.container {
width: 100%;
height: 100%;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

React - Create tag dynamically from ES6 template literal with JSX

I need to display a header element in a React render method where the level is dynamically set in the constructor:
class HeaderComponent extends React.Component {
constructor(props){
super(props);
this._checkedDepth = Math.min(6, props.depth)
}
render(){
return(<h{ this._checkedDepth }>{ this.props.name }</h{ this._checkedDepth }>)
}
}
ReactDOM.render(
<HeaderComponent name="Header 1" depth="2"/>,
document.getElementById('app')
);
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
This should render <h2>Header 1</h2> with name="Header 1" and depth=2, but I get an error instead:
Uncaught Error: Cannot find module "./HeaderComponent"
What am I overlooking?
I'm using React 15.4.1, babel-preset-es2015 6.9.0, babel-preset-react 6.5.0 and running it in Chrome 55.
Each JSX element is just syntactic sugar for calling
React.createElement(component, props, ...children). So, anything you
can do with JSX can also be done with just plain JavaScript. -
https://facebook.github.io/react/docs/react-without-jsx.html
So you can do something like this:
render() {
return React.createElement(`h${this._checkedDepth}`, this.props)
}
Maybe a bit too late, but you can create a component or tag dynamically without using React.createClass with JSX putting the tag name in a variable and using that variable as you would with any other component.
In your case, inside render, you should have something like:
const TitleTag = `h{ this._checkedDepth }>`;
return <TitleTag>{ this.props.name }</TitleTag>
Note the first character of that variable must be uppercase in order to let React know that's a React component, otherwise a tag with the exact same name (not value) of your variable will be inserted instead.
See https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized:
When an element type starts with a lowercase letter, it refers to a
built-in component like <div> or <span> and results in a string 'div'
or 'span' passed to React.createElement. Types that start with a
capital letter like <Foo /> compile to React.createElement(Foo) and
correspond to a component defined or imported in your JavaScript file.
We recommend naming components with a capital letter. If you do have a
component that starts with a lowercase letter, assign it to a
capitalized variable before using it in JSX.
There's no way to do this without creating that variable, so trying to do it on the fly as you do in your code will not work (compiler limitation).
Here's a fully working example:
class HeaderComponent extends React.Component {
constructor(props) {
super(props);
const depth = Math.max(Math.min(parseInt(props.depth) || 1, 6), 1);
this.state = { depth };
}
onClick() {
let depth;
do {
depth = Math.floor(Math.random() * 6) + 1;
} while(depth === this.state.depth);
this.setState({ depth });
}
render() {
const Title = `h${ this.state.depth }`;
return <Title className="title" onClick={ () => this.onClick() }>{ this.props.name }</Title>;
}
}
ReactDOM.render(
<HeaderComponent name="Click Me!" depth="1"/>,
document.getElementById('app')
);
body { margin: 0; }
h1 { font-size: 4rem; }
h2 { font-size: 3.5rem; }
h3 { font-size: 3rem; }
h4 { font-size: 2.5rem; }
h5 { font-size: 2rem; }
h6 { font-size: 1.5rem; }
.title {
margin: 0;
padding: 0 .5rem;
cursor: pointer;
user-select: none;
}
.title:hover {
background: #FFA;
}
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

integrating js code inside react component

I have converted a component that displays chart bar, and it requires this js snippet to run, what is the correct way of integrating it inside my JSX code?
<script>
/** START JS Init "Peity" Bar (Sidebars/With Avatar & Stats) from sidebar-avatar-stats.html **/
$(".bar.peity-bar-primary-avatar-stats").peity("bar", {
fill: ["#2D99DC"],
width: 130,
})
</script>
I have seen this libraries on npm website, but they mostly deal with external scripts not internal
here is my component:
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
<div>
"How can I render js code here?"
</div>
);
}
}
You can use refs and componentDidMount callback in order to initialize jquery plugins, like so
class App extends React.Component {
componentDidMount() {
$(this.barChart).peity("bar", {
fill: ["#2D99DC"], width: 130
});
}
render() {
return <div>
<div ref={ (node) => { this.barChart = node } }>
<span class="bar">5,3,9,6,5,9,7,3,5,2</span>
<span class="bar">5,3,2,-1,-3,-2,2,3,5,2</span>
<span class="bar">0,-3,-6,-4,-5,-4,-7,-3,-5,-2</span>
</div>
</div>;
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/peity/3.2.1/jquery.peity.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
You should use componentDidMount lifecycle hook.
Add this to your component code:
componentDidMount() {
$(".bar.peity-bar-primary-avatar-stats").peity("bar", {
fill: ["#2D99DC"],
width: 130,
})
}

Resources