Unable to update react range values through input - reactjs

I'm writing a code where I'm using react-range to create a range bar. along with it, I've got 2 textboxes that have the min and max values of the range. Currently, I'm able to update the range values by dragging and the text boxes get updated automatically. And I also want to update the price range using the textboxes mentioned, currently, the min box value works fine, but, when I try to update the max value, the value gets appended instead of updating. Unable to know where I'm going wrong.
Here is the code of the same.
import { useState } from "react";
import { Range, getTrackBackground } from "react-range";
export const PriceRange = () => {
const [priceValues, setPriceValues] = useState([1, 100]);
let step = 1;
const handleChange = (values: number[]) => {
if (values[0] > values[1]) {
values[0] = values[1];
}
if (values[1] < values[0]) {
values[1] = values[0];
}
setPriceValues(values);
};
return (
<>
{
<div
style={{
width: "50%",
maxWidth: "50%",
marginLeft: "auto",
marginRight: "auto"
}}
>
<div className="mb-8 text-gray-900 text-sm font-medium text-left">
Price
</div>
<div
style={{ padding: "1rem", marginTop: "1rem", marginBottom: "1rem" }}
>
<Range
step={step}
min={priceValues[0]}
max={priceValues[1]}
values={priceValues}
onChange={(values) => handleChange(values)}
renderTrack={({ props, children }) => (
<div
{...props}
style={{
...props.style,
background: getTrackBackground({
values: priceValues,
colors: ["#c4c4c442", "black", "#c4c4c442"],
min: priceValues[0],
max: priceValues[1]
}),
height: "0.5rem",
width: "100%"
}}
>
{children}
</div>
)}
renderThumb={({ index, props }) => (
<div
{...props}
style={{
...props.style
}}
className="thumbs"
>
<div className="priceValues">{`$${
priceValues[index] === priceValues.length - 1
? priceValues[index] + "+"
: priceValues[index]
}`}</div>
</div>
)}
/>
</div>
<div className="rangeBoxesContainer">
<div className="rangeBox">
<div style={{ display: "flex" }}>Min $</div>
<input
className="rangeInputbox"
type="number"
value={priceValues[0]}
onChange={(e) => {
if (Number(e.target.value) < Number(priceValues[1])) {
let newValue = [...priceValues];
newValue[0] = Number(e.target.value);
setPriceValues(newValue);
}
}}
/>
</div>
<div className="rangeBox">
<div style={{ display: "flex" }}>Max $</div>
<input
className="rangeInputbox"
type="number"
value={priceValues[1]}
onChange={(e) => {
if (Number(e.target.value) > Number(priceValues[1])) {
let newValue = [...priceValues];
newValue[1] = Number(e.target.value);
setPriceValues(newValue);
}
}}
/>
</div>
</div>
</div>
}
</>
);
};
And here is a working code sandbox link. Can someone let me know where I'm going wrong?
Thanks

Related

Setting content editable returns Cannot create property 'contentEditable' on string error

I am visualising a List of Cards with content and what I want to achieve is to set contentEditable=true to the clicked card via its button. I am able to select the content of the element, however contentEditable is not set to true and it returns the following error instead:
Uncaught TypeError: Cannot create property 'contentEditable' on string
And I cant figure out why. What am I doing wrong here and how can I set contentEditable to true for the clicked element via its button?
Here is my code:
import * as React from 'react';
import { ListView } from '#progress/kendo-react-listview';
import { Input } from '#progress/kendo-react-inputs';
import {
Card,
CardTitle,
CardImage,
CardActions,
CardBody,
} from '#progress/kendo-react-layout';
import { Pager } from '#progress/kendo-react-data-tools';
import articles from '../data/articles.json';
import { BubbleChart } from "../components/products/BubbleChart"
const onEdit = (item) => {
console.log(item.Content)
let cardContent = item.Content.contentEditable = "true";
return cardContent
}
const MyItemRender = (props) => {
let item = props.dataItem;
return (
<div
style={{
padding: '20px 20px',
}}
className="parent-container"
>
<div className="k-card-list">
<Card
style={{
width: 260,
height: 340
}}
>
<CardBody
style={{
borderBottom: 'solid 1px rgba(0,0,0,.08)'
}}
>
<CardImage
src={require(`../assets/article-images/${item.Image}`)}
style={{
width: 260,
height: 140,
maxWidth: 260,
}}
/>
<CardTitle
style={{
fontSize: 18,
}}
/>
<CardTitle>{item.Title}</CardTitle>
<CardTitle>{item.Subtitle}</CardTitle>
<p className="content">
Some quick example text to build on the card title and make up the
bulk of the card content.
</p>
</CardBody>
<CardActions>
<div className="footer-buttons-container">
<span>
<span className="k-button k-button-md k-button-rectangle k-rounded-md k-button-flat k-button-flat-base">
<span className="k-icon k-i-preview"></span>Review
</span>
</span>
<span>
<span className="k-button k-edit-button k-button-md k-button-rectangle k-rounded-md k-button-flat k-button-flat-primary" onClick={() => onEdit(item)}>
<span className="k-icon k-i-edit"></span>Edit
</span>
</span>
</div>
</CardActions>
</Card>
</div>
</div>
);
};
export const Products = () => {
const [filteredList, setFilteredList] = React.useState(articles);
const [value, setValue] = React.useState('');
const [page, setPage] = React.useState({
skip: 0,
take: 10,
});
const handlePageChange = (e) => {
setPage({
skip: e.skip,
take: e.take,
});
};
const handleChange = React.useCallback((event) => {
setValue(event.target.value);
const results = articles.filter(post => {
if (event.target.value === "") return articles
return post.Title.includes(event.target.value)
})
console.log(results)
setFilteredList(results)
});
const { skip, take } = page;
return <div>
<div className="chart-container">
<br/>
<br/>
<BubbleChart/>
</div>
<div className="input-container">
<Input
style={{
border: '2px solid #ccc',
boxShadow: 'inset 0px 0px 0.5px 0px rgba(0,0,0,0.0.1)',
}}
placeholder={'Search'}
value={value}
onChange={handleChange}
/>
</div>
<div className="listbox-card-container">
<ListView
data={filteredList.slice(skip, skip + take)}
item={MyItemRender}
style={{
width: '100%',
height: '100%',
}}
/>
<Pager
skip={skip}
take={take}
onPageChange={handlePageChange}
total={articles.length}
/>
</div>
</div>
}
Can't do multiple assigning in one line. add separate lines
const onEdit = (item) => {
console.log(item.Content)
const content = {...item.Content }
content.contentEditable = "true";
return content
}

How to keep the checkbox state saved after page refresh?

I am making a product comparison page. I am trying to keep the checkbox checked after page refresh. Actually I have a products page where each product has a checkbox beneath it. When I click the checkbox, that specific product is added to local Storage + comparison page which I have made. But when I refresh the page, that product is saved but checkbox is unchecked but I want to keep checkbox checked and if checkbox is unchecked, that specific item should be removed from comparison page. How do I solve this query. I have tried several times but not able to do this?? Below is my code
function Home()
{
let history = useHistory()
const getLocalItems = () => {
let compare = localStorage.getItem('compare')
console.log(compare)
if(compare){
return JSON.parse(localStorage.getItem('compare'))
}
else{
return []
}
}
const [comparison,showcomparison] = useState(getLocalItems())
const [item,setItems] = useState()
const [show,setShow] = useState(false)
function onAdd(record){
const exist = comparison.find((x) => x.id === record.id)
if(exist){
showcomparison(comparison.map((x) => x.id === record.id ? {...exist, quantity: exist.quantity+1} : x)
);
}
else
{
showcomparison([...comparison,{...record,quantity: 1}])
}
}
useEffect(() => {
localStorage.setItem('compare',JSON.stringify(comparison))
}, [comparison])
const removeAll = () => {
showcomparison([])
}
return(
<div className="Home">
{
records.map(record => {
return(
<div className='container' key={record.id} onAdd = {onAdd}>
<div className='row'>
<div className='col-xl-3'>
<img style={{width: '100%', height: 'auto'}} src={record.img1} alt=""/><br></br>
<input type='checkbox' value={record.img1} onChange={() => onAdd(record)} style={{paddingRight: '30%'}}/>Compare
</div>
<div className='col-xl-4'>
<p style={{textAlign: 'left', fontWeight: 'bold', fontSize: '18px'}}>{record.title}</p>
<p style={{textAlign: 'left', fontWeight: 'bold', fontSize: '18px'}}>{record.title2}</p>
<p style={{textAlign: 'left', fontWeight: 'bold', fontSize: '18px'}}>{record.title3}</p>
<p style={{textAlign: 'left', fontSize: '15px'}}>MFG#: {record.MFG} | CDW#: {record.CDW}</p>
<p style={{fontWeight: '650', textAlign: 'left'}}>Laptop Type: {record.Type}</p>
<p style={{fontWeight: '650',textAlign: 'left'}}>Screen size: {record.size}</p>
<p style={{fontWeight: '650',textAlign: 'left'}}>Processor Type: {record.ptype}</p>
<p style={{fontWeight: '650',textAlign: 'left'}}>Processor Speed: {record.pspeed}</p>
<p style={{fontWeight: '650',textAlign: 'left'}}>Hard Drive Capacity: {record.capacity}</p>
</div>
<div className='col-xl-3'>
<ul>
<li style={{color: 'green', marginBottom: '1px', textAlign: 'left', fontSize: '13.5px', fontWeight: '640'}}><p>{record.Availability}</p></li>
</ul>
<p style={{fontSize: '13px', textAlign: 'left'}}>Ships today if ordered within 6 hrs 21 mins</p>
<h4 style={{textAlign: 'left', fontFamily: '"Source Serif Pro",serif', fontWeight: 'bold'}}>{record.price}</h4>
<p style={{textAlign: 'left'}}>Advertised Price</p>
<div className='input-group'>
<button type='button' onClick={handleDecrement} className='input-group-text'>-</button>
<div className="form-control text-center"> {quantity} </div>
<button type='button' onClick={handleIncrement} className='input-group-text'>+</button>
</div><br></br>
<button style={{width: '100%', background: '#150404', color: 'white', fontSize: '17.5px', fontWeight: '600', height: '18%'}}>Add to Cart</button>
</div>
</div><hr></hr>
</div>
)
})
}
You can use useRef on the input checkbox, use the following property to set it checked or unchecked.
checkRef.current.checked=false
<input type='checkbox' ref={checkRef} value={record.img1} onChange={() =>
onAdd(record)} style={{paddingRight: '30%'}}/>Compare
use the checkRef.current to change the value with useState.

How can I add the 'All' checkbox in order to select all the other options?

how can I add the All checkboxes that will select all the other checkboxes for each Type of plant and adding a checkbox in front of each Type of plant section. So when I select one option Plant 1.1 then my checkbox for Type of plant #1 is filled, and if option is filled then the checkbox for Type of plant is not filled.
export default function Category({
_id_type,
name_type,
plants,
changeSelection
}) {
const [toggleState, setToggleState] = useState(false);
return (
<div key={_id_type}>
<div
style={{
cursor: "pointer",
userSelect: "none",
display: "flex",
margin: "2px",
backgroundColor: "lightgray"
}}
onClick={() => setToggleState((prev) => !prev)}
>
<div>{name_type}</div>
<div
style={{
backgroundColor: "blue",
color: "white",
padding: "0px 10px",
marginLeft: "auto"
}}
>
{plants.filter(({ selected }) => selected).length}
</div>
</div>
<div style={{ marginLeft: "10px" }}>
{toggleState &&
plants.map(({ name, _id, selected }) => (
<div key={_id}>
<input
key={_id}
type="checkbox"
value={name}
checked={selected}
onChange={(e) => changeSelection(_id_type, _id, e.target.value)}
/>
{name}
</div>
))}
</div>
</div>
);
}
Here a picture (what I have/ what I want) :
Here is my code
add new toogle inside category.jsx
{toggleState && plants.length > 1 ? (
<div>
<input
type="checkbox"
value={"all"}
checked={allSelected}
onChange={(e) => {
setAllSelected((v) => {
changeSelection(_id_type, "all", e.target.value, !v);
return !v;
});
}}
/>
All
</div>
) : (
""
)}
edit change selection function:
const changeSelection = (catId, itemId, value, allSelected) => {
setSelectionMenu((prevSelectionMenu) =>
prevSelectionMenu.map((item) => {
if (item._id_type === catId) {
return {
...item,
plants: item.plants.map((plant) => {
if (plant._id === itemId) {
return { ...plant, selected: !plant.selected };
} else if (itemId === "all") {
return { ...plant, selected: allSelected };
}
return plant;
})
};
}
return item;
})
);
};
here the forked code:
https://codesandbox.io/embed/plants-forked-qdmz2h?fontsize=14&hidenavigation=1&theme=dark

Sync scroll react. div block with main scroll on window

I want to synchronize a divs scroll with a body scroll.
I tried some examples with two divs but I couldn't manage fix it with the body scroll.
Sample code with two divs: https://codesandbox.io/s/react-custom-scroll-sync-of-2-divs-10xpi
My Code
https://codesandbox.io/s/funny-rain-ditbv
import "./styles.css";
import { useRef } from "react";
export default function App() {
const firstDivRef = useRef();
const secondDivRef = useRef();
const handleScrollFirst = (scroll) => {
secondDivRef.current.scrollTop = scroll.target.scrollTop;
};
const handleScrollSecond = (scroll) => {
firstDivRef.current.scrollTop = scroll.target.scrollTop;
};
return (
<div
className="App"
style={{
display: "flex",
}}
>
<div
onScroll={handleScrollFirst}
ref={firstDivRef}
style={{
height: "500px",
overflow: "scroll",
backgroundColor: "#FFDAB9",
position: "sticky",
top: "0px"
}}
>
<div style={{ height: 5000, width: 300 }}>
The first div (or it can be tbody of a table and etc.)
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
<div
onScroll={handleScrollSecond}
ref={secondDivRef}
style={{
height: "100%",
backgroundColor: "#EEE8AA"
}}
>
<div style={{ height: 5000, width: 200 }}>
The second div
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
</div>
);
}
It was easy to use different divs rather than using a div and window.
But finally managed to run it with a div and the body.
The trick is they block each other since they listen each others values.
import "./styles.css";
import { useEffect, useRef, useState } from "react";
export default function App() {
const firstDivRef = useRef();
const [scrollTop, setScrollTop] = useState(0);
const [disableBodyScroll, setDisableBodyScroll] = useState(false);
const handleScrollFirst = (scroll) => {
setScrollTop(scroll.target.scrollTop);
};
useEffect(() => {
if (firstDivRef.current && !disableBodyScroll) {
firstDivRef.current.scrollTop = scrollTop;
}
if (disableBodyScroll) {
window.scrollTo(0, scrollTop);
}
}, [firstDivRef, scrollTop, disableBodyScroll]);
useEffect(() => {
const onScroll = () => {
console.log(disableBodyScroll, window.scrollY);
if (!disableBodyScroll) {
setScrollTop(window.scrollY);
}
};
// clean up code
window.removeEventListener("scroll", onScroll);
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, [disableBodyScroll]);
return (
<div
className="App"
style={{
display: "flex"
}}
>
<div
onMouseEnter={() => setDisableBodyScroll(true)}
onMouseLeave={() => setDisableBodyScroll(false)}
onScroll={handleScrollFirst}
ref={firstDivRef}
style={{
height: "500px",
overflow: "scroll",
backgroundColor: "#FFDAB9",
position: "sticky",
top: "0px"
}}
>
<div style={{ height: 5000, width: 300 }}>
The first div (or it can be tbody of a table and etc.)
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
<div
style={{
height: "100%",
backgroundColor: "#EEE8AA"
}}
>
<div style={{ height: 5000, width: 200 }}>
The second div
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
</div>
);
}
https://codesandbox.io/s/ancient-dream-tzuel?file=/src/App.js
Try the next example. This is a quick sketch but maybe it will help you.
https://codesandbox.io/s/gallant-goldwasser-19g4d?file=/src/App.js

Reset states of a component when it is closed

I have created a MERN application in which on dashboard when a button is clicked a modal box opens which contains some inputs and some options to be selected which are handled using react state hooks. I want when I close modal box the value in it should be reset to default one and when i reopen it all the options should reset to default value
Here is my modal box code
import React, { useState, useContext, useEffect } from "react";
import { UserContext } from "./UserContext";
function SplitModal({
setsplitmodal,
cost,
list,
listobj,
setlistobj,
equal,
setEqual,
payer,
setPayer,
part,
setPart,
setM,
}) {
const [method, setMethod] = useState(true);
const [split, setsplit] = useState(true);
const [owe, setowe] = useState(true);
const [owes, setowes] = useState(true);
const [click, setClick] = useState(false);
const [amount, setAmount] = useState();
const [total, setTotal] = useState(0);
const { user, userfriend } = useContext(UserContext);
console.log(user, "user hu darta koni", user.name);
console.log(listobj);
useEffect(() => {
if (equal === "unequally") {
const _listobj = { ...listobj };
Object.keys(listobj).map((f) => {
_listobj[f] = 0;
});
setlistobj(_listobj);
document.getElementById("InputId").value = "";
console.log(_listobj, "listobjsehu");
}
}, [list, cost]);
const func1 = () => {
setM(false);
setEqual("unequally");
setMethod(false);
const _list = { ...listobj };
_list[list[0]] = -cost;
_list[list[1]] = cost;
setlistobj(_list);
setowe(false);
setowes(true);
setPayer(list[1]);
setPart(`(You owe ${list[1]} ₹${cost})`);
};
const func2 = () => {
setM(false);
setEqual("unequally");
setMethod(false);
const _list = { ...listobj };
const b = _list[list[0]];
_list[list[0]] = +cost;
_list[list[1]] = -cost;
setlistobj(_list);
setPayer(list[0]);
setowe(true);
setowes(false);
setPart(`(${list[1]} owes you ₹${cost})`);
// console.log(owe, owes, click);
};
const distriequal = () => {
setM(true);
// setowe(true);
// setowes(true);
setPart(`(₹${(cost / list.length).toFixed(2)}/person)`);
setMethod(true);
setEqual("equally");
setTotal(0);
const _list = { ...listobj };
list.map((f) => {
if (f === payer) {
_list[f] = (cost - cost / list.length).toFixed(2);
} else {
_list[f] = -(cost / list.length).toFixed(2);
}
setlistobj(_list);
});
};
// console.log(listobj.exp[list[1]], listobj);
const distriamount = (e, i) => {
if (e.key === "Backspace") setM(true);
if (parseInt(e.target.value) > cost) setAmount("err");
else setAmount("");
// console.log( a.replace(a,e.targetvalue));
const _list = { ...listobj };
if (list[i] === payer) {
// _list[list[i]] = e.target.value;
// setOwner(e.target.value);
_list[payer] = parseInt(cost - e.target.value);
} else {
_list[list[i]] = -e.target.value;
}
setlistobj(_list);
if (listobj[user.name] > 0)
setPart(`You get back ₹${Math.abs(_list[user.name])}`);
else if (listobj[user.name] < 0)
setPart(`You owe ₹${Math.abs(_list[user.name])}`);
else setPart(`You owe nothing`);
};
// useEffect(() => {
// Object.keys(listobj).map((f) => {
// if (f === user.name) {
// console.log("nmnm");
// setTotal(total + owner);
// } else setTotal(total + Math.abs(listobj[f]));
// });
// }, [listobj]);
console.log(listobj, list);
return (
<div>
<div className="splitmodal">
<div
style={{
backgroundColor: "#1cc29f",
border: "1px solid #eeeeee",
padding: "5px",
display: "flex",
borderRadius: "10px 10px 0px 0px",
color: "white",
}}
>
<h5 style={{ marginLeft: "100px" }}>Choose Payer</h5>
<button
style={{ position: "absolute", right: "10px" }}
onClick={() => {
setsplitmodal(false);
}}
>
<i class="fas fa-times" />
</button>
</div>
{list.length === 2 ? (
<div className="bg-white splitmodal-main1">
<button
onClick={() => {
setMethod(true);
setM(true);
setClick();
setowe(true);
setowes(true);
}}
>
Split the expense
</button>
<button
onClick={() => {
{
setClick("owe");
return owe ? func1() : null;
}
}}
className={click === "owe" ? "click" : null}
>
You owe {list[1]} ₹{cost}
</button>
<button
className="mb-2"
onClick={() => {
{
setClick("owes");
return owes ? func2() : null;
}
}}
className={click === "owes" ? "click" : null}
>
{list[1]} owes you ₹{cost}
</button>
</div>
) : null}
{method ? (
<div className="splitmodal-main2">
<hr style={{ margin: "10px" }} />
<div className="flex justify-content-center">
<button
style={{
border: "1px solid #ccc",
borderRadius: "5px 0px 0px 5px",
}}
className={equal === "equally" ? "select" : "deselect"}
onClick={() => {
distriequal();
}}
>
Split equally
</button>
<button
style={{
border: "1px solid #ccc",
borderRadius: "0px 5px 5px 0px",
}}
className={equal === "unequally" ? "select" : "deselect"}
onClick={() => {
setEqual("unequally");
}}
>
Split by amounts
</button>
</div>
{equal === "equally" ? (
<div>
<div className="splitmodal-main3">
<h5 className="mt-2 ml-3">Split equally</h5>
<ul
style={{
display: "flex",
flexDirection: "column",
marginLeft: "10px",
}}
>
{list.map((f) => {
return (
<li className="flex align-items-center m-2">
<img
src="https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-grey47-50px.png"
alt=""
/>
<span className="ml-2 font-bold">{f}</span>
<span className="absolute right-10 ">
₹{cost ? (cost / list.length).toFixed(2) : 0.0}
</span>
</li>
);
})}
</ul>
</div>
</div>
) : (
<div>
<div className="splitmodal-main3">
<h5 className="mt-2 ml-3">Split by amounts</h5>
<ul
style={{
display: "flex",
flexDirection: "column",
marginLeft: "10px",
}}
>
{list.map((f, i) => {
return (
<li key={i} className="flex align-items-center m-2">
<img
src="https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-grey47-50px.png"
alt=""
/>
<span className="ml-2 font-bold">{f}</span>
<span className="absolute right-5 ">
<span
style={{
backgroundColor: "#EEEEEE",
paddingLeft: "14px",
paddingRight: "14px",
border: "1px solid #ccc",
borderRadius: "4px 0px 0px 4px",
}}
>
₹
</span>
<input
type="number"
// value={Math.abs(listobj[f])}
id="InputId"
style={{
width: "60px",
border: "1px solid #ccc",
borderRadius: "0px 4px 4px 0px",
height: "23.33px",
}}
className={
amount === "err" ? "text-red-500" : null
}
onChange={(e) => {
distriamount(e, i);
}}
/>
</span>
</li>
);
})}
</ul>
</div>
{/* <div className="mt-2 ml-3">
<h5>Total:</h5>
<span className="absolute right-10 bottom-0 ">₹{total}</span>
</div> */}
</div>
)}
</div>
) : null}
</div>
</div>
);
}
export default SplitModal;
Please help me solving this
As a workaround you can write a new useEffect() that reset all the value at the loading of your component, something like :
useEffect(() => {
setMethod(true);
setsplit(true);
setowe(true);
setowes(true);
setClick(false);
setAmount();
setTotal(0);
}, []);
We don't actually need a separate effect to perform the cleanup. useEffect is designed to keep it together.
Learn more on: https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup
useEffect(() => {
// your other codes
return function reset() {
setMethod(true);
setsplit(true);
setowe(true);
setowes(true);
setClick(false);
setAmount(0);
setTotal(0);
}
}, []);

Resources