How do I dynamically adjust the size of the React chart 2 pie chart - reactjs

titles come dynamically. The number is not clear. That's why I can't give a fixed height. The graphic is getting smaller. How can I make the chart size dynamic ?
const options = {
legend: {
"position": "bottom",
align:'start',
display:true,
itemWrap: true,
},
responsive: true,
maintainAspectRatio: false,
animation: false,
};
<div className={styles['department-charts__card__altCard']}>
<Doughnut
data={doughnutData}
options={options}
/>
</div>
If the Legend is too much, the graphic gets smaller. With Legend, the chart does not appear in a separate container. When I check it looks like this
<canvas height="600" width="542" class="chartjs-render-monitor" style="display: block; height: 300px; width: 271px;"></canvas>
I want the cake to be at least 300 pixels. With Legend it will be more comfortable to check whether the pie is in a different container. How can I make this show dynamic? Pie does not appear at all on small screens. If there are 3 or 4 in some values, it is not a problem. If it's too much, it doesn't fit. I don't want to hide the legend

Amme hizmeti,
Ben bu şekilde çözdüm. Özel bir efsane yarattım
import { Doughnut } from 'react-chartjs-2';
const options = {
legend: {
"position": "bottom",
display:false,
},
responsive: true,
maintainAspectRatio: false,
animation: false,
offset:true
};
let chartInstance = null;
const DepartmentCharts = ({
t, departmentDistribution
}) => {
const keys = departmentDistribution.map(it => {
const key = it.key
return t(key)
}) || [t('salesAndMarketing'), t('ik'), t('management')]
const values = departmentDistribution.map(it => it.value) || [0, 0, 0]
const doughnutData = {
labels: keys,
datasets: [{
data: values,
backgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#8bc34a',
'#6c429b',
'#00a860',
'#0154a3',
'#f78f1e',
"#CCCC99",
"#666666",
"#FFCC66",
"#6699CC",
"#663366",
"#9999CC",
"#CCCCCC",
"#669999",
"#CCCC66",
"#CC6600",
"#9999FF",
"#0066CC",
"#99CCCC",
"#999999",
"#FFCC00",
"#009999",
"#99CC33",
"#FF9900",
"#999966",
"#66CCCC",
"#339966",
"#CCCC33",
"#003f5c",
"#665191",
"#a05195",
"#d45087",
"#2f4b7c",
"#f95d6a",
"#ff7c43",
"#ffa600",
"#EF6F6C",
"#465775",
"#56E39F",
"#59C9A5",
"#5B6C5D",
"#0A2342",
"#2CA58D",
"#84BC9C",
"#CBA328",
"#F46197",
"#DBCFB0",
"#545775"
],
hoverBackgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#8bc34a',
'#6c429b',
'#00a860',
'#0154a3',
'#f78f1e',
"#CCCC99",
"#666666",
"#FFCC66",
"#6699CC",
"#663366",
"#9999CC",
"#CCCCCC",
"#669999",
"#CCCC66",
"#CC6600",
"#9999FF",
"#0066CC",
"#99CCCC",
"#999999",
"#FFCC00",
"#009999",
"#99CC33",
"#FF9900",
"#999966",
"#66CCCC",
"#339966",
"#CCCC33",
"#003f5c",
"#665191",
"#a05195",
"#d45087",
"#2f4b7c",
"#f95d6a",
"#ff7c43",
"#ffa600",
"#EF6F6C",
"#465775",
"#56E39F",
"#59C9A5",
"#5B6C5D",
"#0A2342",
"#2CA58D",
"#84BC9C",
"#CBA328",
"#F46197",
"#DBCFB0",
"#545775"
]
}]
};
const handleClick = (e, index) => {
const ctx = chartInstance.chartInstance;
const meta = ctx.getDatasetMeta(0);
// See controller.isDatasetVisible comment
meta.data[index].hidden = !meta.data[index].hidden;
// Toggle strikethrough class
if (e.currentTarget.classList.contains("disable-legend")) {
//console.log("çizgiyi kaldır")
e.currentTarget.classList.remove("disable-legend");
e.currentTarget.style.textDecoration = "inherit";
} else {
//console.log("çizgi çiz")
e.currentTarget.classList.add("disable-legend");
e.currentTarget.style.textDecoration = "line-through";
}
chartInstance.chartInstance.update();
};
useEffect(() => {
const legend = chartInstance.chartInstance.generateLegend();
document.getElementById("legend").innerHTML = legend;
document.querySelectorAll("#legend li").forEach((item, index) => {
item.addEventListener("click", (e) => handleClick(e, index));
});
}, [doughnutData]);
return (
<div className={styles['department-charts']}>
<Card className={styles['department-charts__card']}>
<CardHeader
title={`${t('departmentTitle')}`}
align='center'
/>
<CardContent>
<div className={styles['department-charts__card__altCard']}>
<Doughnut
data={doughnutData}
options={options}
ref={input => {
chartInstance = input;
}}
/>
</div>
<div id="legend" className={styles['department-charts__card__altCard__legend']}/>
</CardContent>
</Card>
</div>
);
};
style.css - efsane kısmı sizin için yeterli olabilir
.department-charts {
height: 100%;
&__card {
height: 100%;
padding: 16px;
&__altCard{
min-height: 235px;
&__legend{
color: #666666;
ul{
list-style: none;
font: 12px Verdana;
white-space: nowrap;
display: inline-block;
padding-top: 20px;
font-family: "Helvetica Neue";
}
li{
cursor: pointer;
float: left;
padding-left: 7px;
span{
width: 36px;
height: 12px;
display: inline-block;
margin: 0 5px 8px 0;
vertical-align: -9.4px;
}
}
}
}
}
}
.disable-legend {
text-decoration: line-through;
}

Related

React how to repopulate values when back button clicked

In react js i get value from api then i used component to populated vale after back button clicked i don`t want to remove my value i want to my current data that work in text filed but it not work on
select it always remove it value.it show error name not defined.
i want repopulate select when clicked back button
import React from 'react';
import styled from 'styled-components';
import Select from 'react-select';
import { useNavigate } from 'react-router-dom';
import { QsrQoreApi, Eats365, StoreHub } from './Sources';
import SourceStoreSelection from './SourceStoreSelection';
import svgs from '../../shared/svgs';
import { Modal, withAuth } from '../../shared';
const StyledSourceSettings = styled.div`
& .header {
display: flex;
height: 5.2rem;
align-items: center;
border-bottom: 0.1rem solid #edf2f7;
}
& .back {
height: 2rem;
width: 2rem;
margin-left: 2rem;
}
& .title {
margin-left: max(1.5rem, calc(((100vw - 21rem) / 2) - 4rem));
width: 21rem;
height: 2rem;
font-size: 1.6rem;
font-weight: 700;
line-height: 2rem;
text-align: center;
color: #2d3748;
}
& .source-form {
padding: 2rem;
display: grid;
grid-template-columns: 1fr;
}
& .login {
width: 28rem;
margin: 0 auto 0.4rem auto;
font-size: 1.6rem;
font-weight: 700;
color: #2d3748;
}
& .form-input {
margin: 1.5rem auto 0 auto;
width: 28rem;
font-size: 1.6rem;
color: #4a5568;
}
& .form-input > .input {
width: 28rem;
margin: 0.5rem 0 0 0;
height: 3.6rem;
font-size: 1.6rem;
border: 0.1rem solid #a0aec0;
border-radius: 0.4rem;
color: #4a5568;
padding: 1rem;
}
& .form-input > .select {
margin: 0.5rem 0 0 0;
}
& .buffer-152px {
height: 15.2rem;
}
& .buffer-91px {
height: 9.1rem;
}
& .selected-store {
width: 28rem;
height: 2rem;
margin: 2rem auto 0 auto;
font-size: 1.6rem;
font-weight: 700;
color: #2d3748;
}
& .selected-store-detail {
display: flex;
height: 5.1rem;
margin: 0 auto;
align-items: center;
border-bottom: 0.1rem solid #edf2f7;
font-size: 1.6rem;
color: #4a5568;
}
& .selected-store-detail > .map {
height: 2rem;
width: 2rem;
}
& .selected-store-detail > .name {
height: 2rem;
width: 22rem;
margin-left: 1rem;
}
& .selected-store-detail > .forward {
height: 2rem;
width: 2rem;
margin-left: 1rem;
}
& .next-btn {
width: 28rem;
height: 3.6rem;
margin: auto;
margin-top: max(5.3rem, calc(100vh - 47.1rem));
border: 0.1rem solid #cbd5e0;
border-radius: 0.4rem;
background: #ffffff;
box-shadow: 0rem 0.2rem 0.4rem rgba(24, 39, 75, 0.12);
padding: 1rem;
font-size: 1.6rem;
font-weight: 600;
color: #4a5568;
}
& .next-btn:disabled,
& .next-btn[disabled] {
box-shadow: none;
color: #cbd5e0;
}
`;
const sourceOpts = [
{ value: 'QsrQoreApi', label: 'QsrQoreApi' },
{ value: 'Eats365', label: 'Eats365' },
{ value: 'StoreHub', label: 'StoreHub' },
];
const sourceSelectStyles = {
control: (provided) => ({
...provided,
width: '28rem',
minHeight: '3.6rem',
height: '3.6rem',
fontSize: '1.6rem',
border: '0.1rem solid #a0aec0',
borderRadius: '0.4rem',
color: '#4a5568',
}),
indicatorSeparator: () => {},
singleValue: (provided) => ({
...provided,
color: '#4a5568',
}),
valueContainer: (provided) => ({
...provided,
padding: '0.2rem 0.8rem',
}),
placeholder: (provided) => ({
...provided,
margin: 'auto 0.2rem',
}),
input: (provided) => ({
...provided,
margin: '0.2rem',
padding: '0.2rem auto',
}),
dropdownIndicator: (provided) => ({
...provided,
'& svg': {
height: '2rem',
width: '2rem',
},
}),
indicatorsContainer: (provided) => ({
...provided,
'& > div': {
padding: '0.8rem',
},
}),
menu: (provided) => ({
...provided,
borderRadius: '0.4rem',
margin: '0.8rem auto',
}),
menuList: (provided) => ({
...provided,
maxHeight: '30rem',
padding: '0.4rem 0',
}),
option: (provided) => ({
...provided,
padding: '0.8rem 1.2rem',
}),
};
function AddSource(props) {
const { setForm, store, setStore , source} = props;
const [sourceAdditionalInfos, setSourceAdditionalInfos] = React.useState({});
const [sourceStore, setSourceStore] = React.useState(null);
const [showModal, setShowModal] = React.useState(false);
const navigate = useNavigate();
React.useEffect(() => {
if(store.source){
const infos = store.source.additionalInfos.reduce((result, { key, value }) => {
const temp = result;
temp[key] = value;
return temp;
}, {});
setSourceAdditionalInfos(infos);
}
},[]);
React.useEffect(() => {
if (store.source) {
const infospos = store.source.type
const value = infospos;
setSourceStore(value);
}
},[]);
const onBackClick = () => {
navigate(-1);
};
const onSourceSelectChange = (source) => {
if (source) {
setStore({ ...store, source: { type: source.value } });
setSourceStore(null);
}
};
const handleChange = (e) => setSourceAdditionalInfos({ ...sourceAdditionalInfos, [e.target.id]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
if (!sourceStore) setShowModal(true);
else {
const addInfos = Object.entries(sourceAdditionalInfos).map(([k, v]) => ({ key: k, value: v }));
let st = {
...store,
source: {
...store.source,
...sourceStore.value,
additionalInfos: addInfos.concat(sourceStore.value.additionalInfos),
},
};
setStore(st);
setForm('addStore');
}
};
let renderSource = <div className="buffer-152px" />;
if (store.source) {
switch (store.source.type) {
case 'QsrQoreApi':
renderSource = (
<QsrQoreApi
handleChange={handleChange}
sourceAdditionalInfos={sourceAdditionalInfos}
disableInput={sourceStore}
/>
);
break;
case 'Eats365':
renderSource = (
<Eats365
handleChange={handleChange}
sourceAdditionalInfos={sourceAdditionalInfos}
disableInput={sourceStore}
/>
);
break;
case 'StoreHub':
renderSource = (
<StoreHub
handleChange={handleChange}
sourceAdditionalInfos={sourceAdditionalInfos}
disableInput={sourceStore}
/>
);
break;
default:
renderSource = <div className="buffer-152px" />;
break;
}
}
let renderSelectedSourceStore = '';
if (sourceStore) {
renderSelectedSourceStore = (
<>
<div className="selected-store">Store selection</div>
<div className="selected-store-detail" onClick={() => setShowModal(true)}>
<img src={svgs.map} className="map" alt="map" />
<div className="name">{sourceStore.value.name}</div>
<img src={svgs.forward} className="forward" alt="forward" />
</div>
</>
);
} else {
renderSelectedSourceStore = <div className="buffer-91px" />;
}
return (
<StyledSourceSettings>
<div className="header">
<img src={svgs.back} className="back" alt="back" onClick={onBackClick} />
<div className="title">POS System</div>
</div>
<form className="source-form" onSubmit={onSubmit}>
<div className="login">Login credentials</div>
<label className="form-input" htmlFor="type">
<div className="label">POS System</div>
<div className="select">
<Select
options={sourceOpts}
styles={sourceSelectStyles}
placeholder="Choose one"
onChange={onSourceSelectChange}
inputId="type"
isDisabled={sourceStore}
/>
</div>
</label>
{renderSource}
{renderSelectedSourceStore}
<input className="next-btn" type="submit" value="NEXT" disabled={!(store.source && store.source.type)} />
</form>
<Modal onClose={() => setShowModal(false)} open={showModal}>
<SourceStoreSelection
onSubmitted={() => setShowModal(false)}
onClosed={() => setShowModal(false)}
store={store}
sourceAdditionalInfos={sourceAdditionalInfos}
sourceStore={sourceStore}
setSourceStore={setSourceStore}
/>
</Modal>
</StyledSourceSettings>
);
}
export default withAuth(AddSource);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
enter image description here
Try to change it to:
{sourceStore?.value?.name}

React ag-grid row auto height doesn't work

I was trying to implement the row auto height feature described in the docs here:
https://www.ag-grid.com/javascript-grid-row-height/#auto-row-height
However it seems to not be working in my case. What happens for me is that the text doesn't wrap at all and it just creates a single long line for each row.
I've tried adapting the code as best as I could to my own app, but maybe I missed something? I'll be thankful if you could take a look at my code and tell me if something is missing:
const defaultColDefProperties = {
flex: 1,
editable: true,
resizable: true,
floatingFilter: true,
filter: true,
wrapText: true,
autoHeight: true,
};
const columnDefinition = [{headerName: "Key", field: "Key"},
{headerName: "Value", field: "Value"}];
const ConfigurationDataGrid = (props) =>
{
const [gridRowData, setGridRowData] = useState([]);
const gridApi = useRef(null);
useEffect(async () =>
{
const getRowData = async () =>
{
let rowData = await WebApi.getRowData();
setGridRowData(rowData);
}
await getRowData();
},[]);
const onGridReady = params =>
{
gridApi.current = params.api;
}
const onColumnResized = (params) =>
{
params.api.resetRowHeights();
}
const onColumnVisible = (params) =>
{
params.api.resetRowHeights();
}
return (
<div style={{ width: '100%', height: '100%' }}>
<UxDataGrid
id='datagrid'
className='custom-datagrid'
onGridReady={onGridReady}
columnDefs={columnDefinition}
rowData={gridRowData}
defaultColDef={defaultColDefProperties}
onColumnResized={onColumnResized}
onColumnVisible={onColumnVisible}/>
</div>
);
}
The css class:
.custom-datagrid {
height: 100%;
border: 0px;
margin-top: 0px !important;
margin-right: 0px !important;
margin-left: 0px !important;
}
What am I missing?
In my case I have ra-ui-grid it is the same as your component - UxDataGrid
Inside ra-ui-grid I have next definitions:
.html:
<ag-grid-angular
class="ag-theme-balham grid"
...
></ag-grid-angular>
.ts:
defaultColDef: {
flex: 1,
...
},
.scss:
ra-ui-grid {
height: 100%;
display: flex;
flex-flow: column nowrap;
.grid {
height: 100%;
}
}
Then in some component, I am using ra-ui-grid with 2 wrappers
.html
<div class="io">
<div class="io__table">
<ra-ui-grid
[data]="data"
[config]="gridConfig"
[columns]="columnDefs"
(onPaginationChanged)="paginationChanged.next($event)"
></ra-ui-grid>
</div>
</div>
.scss:
.io {
height: calc(100% - 36px);
display: flex;
flex-direction: column;
&__table {
flex: 1;
min-height: 254px;
}
}

How to display value with '%' react chart-race

i want to display at chart-race value with percentage. example 75%
however, the value of chart-race accepts only number. how would I able to include '%'
here's the code from 'https://www.npmjs.com/package/react-chart-race'
import React, { Component } from 'react';
import ChartRace from 'react-chart-race';
class Form extends Component{
constructor(props){
super(props);
this.state = {
data: []
};
setInterval(() => {
this.handleChange();
}, 0);
}
getRandomInt(min, max){
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
handleChange(){
const data = [
{ id: 0, title: 'Ayfonkarahisar', value: 10, color: '#50c4fe'},
{ id: 1, title: 'Kayseri', value: 20, color: '#3fc42d' },
{ id: 2, title: 'Muğla', value: 30, color: '#c33178' },
{ id: 3, title: 'Uşak', value: 40, color: '#423bce' },
{ id: 4, title: 'Sivas', value: 50, color: '#c8303b' },
{ id: 5, title: 'Konya', value: 60, color: '#2c2c2c' }
];
this.setState({ data });
}
render(){
return(
<div>
<ChartRace
data={this.state.data}
backgroundColor='#000'
width={760}
padding={12}
itemHeight={58}
gap={12}
titleStyle={{ font: 'normal 400 13px Arial', color: '#fff' }}
valueStyle={{ font: 'normal 400 11px Arial', color: 'rgba(255,255,255, 0.42)' }}
/>
</div>
);
}
}
export {Form}
I have made some changes in react-chart-race for label
Now, you do not need to use this dependency use below code in your project
Add this two files to your project
ChartRace.js
import React, { Component } from "react";
import "./chartstyle.css";
export default class ChartRace extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data.sort((a, b) => b.value - a.value),
temp: this.props.data,
maxValue: Math.max.apply(Math, this.props.data.map(item => item.value)),
valueLabel: this.props.valueLabel
};
}
static getDerivedStateFromProps(nextProps, prevState) {
let newProps = [...nextProps.data];
return {
data: nextProps.data,
temp: newProps.sort((a, b) => b.value - a.value),
maxValue: Math.max.apply(Math, nextProps.data.map(item => item.value))
};
}
draw(item, index) {
const indis = this.state.temp.findIndex(temp => temp.id === item.id);
const translateY =
indis === 0
? this.props.padding
: this.props.padding +
indis * this.props.itemHeight +
indis * this.props.gap;
return (
<div
key={index}
className="raceItem"
style={{
height: this.props.itemHeight,
transform:
"translateY(" +
translateY +
"px) translateX(" +
this.props.padding +
"px)"
}}
>
<b
style={{
backgroundColor: item.color,
width:
(item.value / this.state.maxValue) *
(this.props.width - 120 - 2 * this.props.padding)
}}
/>
<span>
<em style={this.props.titleStyle}>{item.title}</em>
<i style={this.props.valueStyle}>
{item.value} {this.state.valueLabel}{" "}
</i>
</span>
</div>
);
}
render() {
return (
<div
className="raceArea"
style={{
backgroundColor: this.props.backgroundColor,
paddingTop: this.props.padding,
paddingBottom: this.props.padding,
width: this.props.width,
height:
2 * this.props.padding +
this.state.temp.length * this.props.itemHeight +
(this.state.temp.length - 1) * this.props.gap
}}
>
{this.state.data.map((item, index) => this.draw(item, index))}
</div>
);
}
}
ChartRace.defaultProps = {
data: [],
backgroundColor: "#f9f9f9",
width: 680,
padding: 20,
itemHeight: 38,
gap: 4,
titleStyle: { font: "normal 400 13px Arial", color: "#212121" },
valueStyle: { font: "normal 400 11px Arial", color: "#777" },
valueLabel: ""
};
chartstyle.css
.raceArea {
box-sizing: border-box;
position: relative;
}
.raceItem {
display: flex;
align-items: center;
position: absolute;
top: 0px;
left: 0px;
transition: all 1200ms;
}
.raceItem b {
height: 100%;
border-radius: 4px;
transition: all 600ms;
background: #dadada;
}
.raceItem span {
width: 112px;
margin-left: 8px;
display: flex;
flex-direction: column;
}
.raceItem em {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.raceItem i {
margin-top: 2px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
Import it like
import ChartRace from "./ChartRace";
Use it like
<ChartRace
data={this.state.data}
backgroundColor="#000"
width={760}
padding={12}
itemHeight={58}
gap={12}
valueLabel="%" // pass your label here
titleStyle={{ font: "normal 400 13px Arial", color: "#fff" }}
valueStyle={{
font: "normal 400 11px Arial",
color: "rgba(255,255,255, 0.42)"
}}
/>

How would this React code look without React-hooks and with class components rather than functional components?

I just studied React from YouTube lessons, and there all the lessons were built on classes and the usual this.setState, without hooks. How would this React code look without React-hooks and with class components rather than functional components?
The code itself implements an image slider:
React:
function Slider({ items }) {
const [ active, setActive ] = React.useState(0);
const { length, [active]: slide } = items;
const next = e => setActive((active + +e.target.dataset.step + length) % length);
const goTo = e => setActive(+e.target.dataset.index);
React.useEffect(() => {
const timeout = setTimeout(() => setActive((active + 1 + length) % length), 5000);
return () => clearTimeout(timeout);
}, [active, length]);
return (
<div>
<div className="slideshow-container">
<div className="mySlides fade">
<div className="numbertext">{active + 1} / {length}</div>
<img src={slide.img} />
<div className="text">{slide.title}</div>
</div>
<a className="prev" onClick={next} data-step={-1}>❮</a>
<a className="next" onClick={next} data-step={+1}>❯</a>
</div>
<div className="dots">
{items.map((n, i) => (
<span
key={n.id}
className={`dot ${i === active ? 'active' : ''}`}
onClick={goTo}
data-index={i}
></span>
))}
</div>
</div>
);
}
const items = [
{ title: 'One', img: 'https://upload.wikimedia.org/wikipedia/commons/1/1f/Purity_of_nature.jpg' },
{ title: 'Two', img: 'https://mairie-balma.fr/wp-content/uploads/2016/06/Lhers.jpg' },
{ title: 'Three', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRt-b1iBqHQ_emkm1wFmkM7KQskzIqg7YQPZWW85Sa7k2nNLwgjMw' },
].map((n, i) => ({ ...n, id: i + 1 }));
ReactDOM.render(<Slider items={items} />, document.getElementById('app'));
HTML
<div id="app"></div>
CSS:
.slideshow-container {
max-width: 500px;
position: relative;
margin: auto;
}
.prev, .next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
.prev:hover, .next:hover {
background-color: rgba(0,0,0,0.8);
}
.text {
color: #f2f2f2;
font-size: 15px;
padding: 8px 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
box-sizing: border-box;
}
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
.dots {
display: flex;
justify-content: center;
}
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active, .dot:hover {
background-color: #717171;
}
.mySlides img {
width: 100%;
}
Something like this (not fully tested):
class Slider {
constructor(props) {
super(props);
this.state = {
active: 0
}
}
let timeout = null;
componentDidMount() {
this.timeout = setTimeout(() => this.setActive(), 5000);
}
componentDidUpdate(prevProps) {
const { active } = this.props;
if (prevProps.active !=== active {
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => this.setActive(), 5000);
});
}
componentDidUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
const setActive = (newActive) => {
const { length } = items;
this.setState({
active: (newActive + 1 + length) % length
});
}
const next = e => {
const { length } = items;
this.setActive((this.state.active + +e.target.dataset.step + length) % length);
}
const goTo = e => this.setActive(+e.target.dataset.index);
render() {
const { length } = items;
const {active} = this.state;
return (
<div>
<div className="slideshow-container">
<div className="mySlides fade">
<div className="numbertext">{active + 1} / {length}</div>
<img src={slide.img} />
<div className="text">{slide.title}</div>
</div>
<a className="prev" onClick={this.next} data-step={-1}>❮</a>
<a className="next" onClick={this.next} data-step={+1}>❯</a>
</div>
<div className="dots">
{items.map((n, i) => (
<span
key={n.id}
className={`dot ${i === active ? 'active' : ''}`}
onClick={this.goTo}
data-index={i}
></span>
))}
</div>
</div>
);
}
}
const items = [
{ title: 'One', img: 'https://upload.wikimedia.org/wikipedia/commons/1/1f/Purity_of_nature.jpg' },
{ title: 'Two', img: 'https://mairie-balma.fr/wp-content/uploads/2016/06/Lhers.jpg' },
{ title: 'Three', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRt-b1iBqHQ_emkm1wFmkM7KQskzIqg7YQPZWW85Sa7k2nNLwgjMw' },
].map((n, i) => ({ ...n, id: i + 1 }));
ReactDOM.render(<Slider items={items} />, document.getElementById('app'));

How to open a multiple message box with ReactJS

I'm building a multiple chatbox messaging like Facebook's popup messenger windows. At the moment, the user can call up a chatbox, close it, minimize it, etc.
When I click on multiple users, say 3, I'm supposed to have three chatboxes pop up corresponding to those three different users. Currently, only one chatbox appears.
This screenshot illustrates what I want to achieve. On each user's button click, it's own chatbox will popup.
Here is the demo and download link for a jQuery equivalent: link.
This is the full React code which shows just one chat box:
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import axios from 'axios';
import './style.css';
class MessageBox extends Component {
constructor() {
super();
this.state = {
showBox: false,
shownToggle: true,
data: [
{ id: "1", name: "Tony" },
{ id: "2", name: "Mark" },
{ id: "3", name: "Joy" }
],
currentRec: undefined,
};
this.showBox = this.showBox.bind(this);
this.closeBox = this.closeBox.bind(this);
this.toggle = this.toggle.bind(this);
}
showBox = (i, pid, name) => {
this.setState({ currentRec: i });
console.log(`Selected record index: ${i}`);
alert(pid);
alert(name);
this.setState({ showBox: true }, () => {
document.addEventListener('click', this.closeBox);
});
}
closeBox(event) {
if (this.dropdownBox.contains(event.target)) {
this.setState({ showBox: false }, () => {
document.removeEventListener('click', this.closeBox);
});
}
}
toggle() {
this.setState({
shownToggle: !this.state.shownToggle
});
}
render() {
var hidden = {
display: this.state.shownToggle ? "block" : "none"
}
return (
<div>
<ul style={{ float: "right" }}>
{this.state.data.map((person, i) => (
<div className="chat-sidebar" key={i}>
<button onClick={() => this.showBox(i, person.id, person.name)}>Chat with {person.name}</button>
{this.state.showBox ? (
<div className="msg_box" style={{ right: '270px' }}>
<div onClick={this.toggle.bind(this)} class="msg_head">
(<b style={{ color: 'orange' }}>
{this.state.currentRec !== undefined &&
<div className="modal-body">
{this.state.data[this.state.currentRec].name}
({this.state.data[this.state.currentRec].id})
</div>
}
</b>)
Minimize
<div className="close" ref={(element) => { this.dropdownBox = element; }} style={{ color: 'white' }}>Close</div>
</div>
<div style={hidden} className="msg_wrap"><div className="msg_body">Message will appear here</div></div>
</div>) : (null)}
</div>
))}
</ul>
</div>
);
}
}
/****** Chat Popup Layout ******/
body{
background: #e5e5e5;
font-family: sans-serif;
}
.msg_box{
position: fixed;
bottom: -5px;
width: 250px;
background: white;
border-radius: 5px 5px 0px 0px;
}
.msg_head{
background: black;
color: white;
padding: 8px;
font-weight: bold;
cursor: pointer;
border-radius: 5px 5px 0px 0px;
}
.msg_body{
background: white;
height: 200px;
font-size: 12px;
padding: 15px;
overflow: auto;
overflow-x: hidden;
}
.close{
float: right;
cursor: pointer;
}
.minimize{
float: right;
cursor: pointer;
padding-right: 5px;
}
/****** Slider Layout Popup ******/
.chat-sidebar {
width: 250px;
height: 100%;
right: 0px;
top: 0px;
padding-top: 10px;
padding-bottom: 10px;
border: 1px solid #b2b2b2;
}
After series of efforts, the use of jquery and Reactjs is what solved my issue as per code below
const dataSet = this.state.data;
alert(dataSet);
if ($.inArray(pid, dataSet) != -1)
{
dataSet.splice($.inArray(pid, this.state.data), 1);
}
dataSet.unshift(pid);
var s = 270 ; // start position
var j = 260; //next position
$.each(dataSet, function( index, value ) {
if(index < 4){
$('[rel="'+value+'"]').css("right",s);
$('[rel="'+value+'"]').show();
s = s+j;
}
else{
$('[rel="'+value+'"]').hide();
}

Resources