Onchange Function for a range input - reactjs

I'm using React.JS for building a range input slider.The value of min , max and value have been set by {this.renderMinTotal()} and {this.renderMaxTotal()}.The main problem is that when I try to toggle it it does not move at all.I know that I should use onChange handler but I do not know what to write.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
library: null,
};
}
componentDidMount() {
fetch("/json.bc", {
method: "get"
})
.then(response => response.text())
.then(text => {
let Maindata = JSON.parse(text.replace(/\'/g, '"'));
this.setState(
state => ({
...state,
data: Maindata
}),
() => {
this.reorganiseLibrary();
}
);
})
.catch(error => console.error(error));
}
reorganiseLibrary = () => {
const { data } = this.state;
let library = data;
library = _.chunk(library);
this.setState({
library,
});
};
handlePerPage = evt =>
this.setState(
{
perPage: evt.target.value
},
() => this.reorganiseLibrary()
);
renderMinTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.reduce((acc, lib) => {
const libMin = Math.min(...lib.map(item => item.totalCom));
return acc === undefined ? libMin : libMin < acc ? libMin : acc;
}, undefined);
};
renderMaxTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.reduce((acc, lib) => {
const libMax = Math.max(...lib.map(item => item.totalCom));
return libMax > acc ? libMax : acc;
}, 0);
};
handlerChange = evt =>{
let value = evt.target.value
///what should be written here///////
}
render() {
const { library } = this.state;
return (
<div>
<div>
<input
type="range"
min={this.renderMinTotal()}
max={this.renderMaxTotal()}
value={this.renderMaxTotal()}
step="1000"
className="multirange"
onChange={this.handlerChange}
/>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('Result'))

i don't see reason to load value of your range-input from
( this.renderMaxTotal() )
try just leaving value blank, later on try f.e.
onChange={(event)=>{console.log(event.target.value)}}

Related

TypeError: (0 , _reactRouterDom.withRouter) is not a function----- Getting this error after updating the application to the latest React version

// App.js - WEB
/* eslint-disable no-undef */
import { hot } from 'react-hot-loader/root';
import React, { Component } from "react";
import { View, Platform, Dimensions, Linking, Text } from "react-native";
import { Routes } from "react-router-dom";
import { ModalContainer } from "react-router-modal";
import IdleTimer from "react-idle-timer";
import {
BroadcastChannel
} from 'broadcast-channel';
import { withRouter } from './utils/withRouterComponent';
const routeMap = {
...CommonRouteMap,
};
class App extends Component {
constructor(props) {
super(props);
this.state = {
backgroundColor: "#F36414",
openmodel: false,
bootboxtext: "",
modalopenhide: false,
measure: getMeasure(this.getWidth()),
workingtime: true,
userIdle: false,
maintainanceText: APP.MAINTAINANCE_TIME,
linearColors: linearColors(),
isDuplicate: false
};
this.handleWindowPerformanceEvents();
// Store the previous pathname and search strings
this.currentPathname = null;
this.currentSearch = null;
this.workingTime = dayjs(new Date()).format("HH");
}
changeBackground = (color) => {
this.setState({ backgroundColor: color });
};
handleLayout = ({ nativeEvent }) => {
const { width } = nativeEvent.layout;
const measure = getMeasure(width);
this.setState(() => ({ measure }));
};
getWidth = () => {
const { width } = Dimensions.get("window");
return width;
};
handleWindowPerformanceEvents = async () => {
let ExternalFlag;
if (Platform.OS === "web") {
ExternalFlag = sessionStorage.getItem("ExternalFlag");
} else {
ExternalFlag = await AsyncStorage.getItem("ExternalFlag");
}
let parts = window.location.pathname.split("/");
let path = parts[parts.length - 1];
if (window.performance) {
if (
performance.navigation.type === 0 &&
!window.location.pathname != "404Page"
) {
localStorage.clear();
} else if (!window.location.pathname != "404Page") {
localStorage.clear();
const pathName = window.location.pathname;
const domainName = window.location.origin;
let updatedPath = pathName.substr(0, pathName.lastIndexOf("/"));
if (paths.includes(updatedPath)) {
if (ExternalFlag == 'false') {
window.location.href = `${domainName}${updatedPath}`;
}
return;
} else {
if (ExternalFlag == 'false') {
window.location.href = `${window.location.origin}/servicing/index.html`;
}
}
}
}
};
async componentDidMount() {
const bc = new BroadcastChannel("MY-Project");
bc.onmessage = (event) => {
if (event === "newTab") {
bc.postMessage(`duplicateTab`);
this.setState({ isDuplicate: false })
}
if (event === `duplicateTab`) {
bc.close()
}
};
bc.postMessage('newTab');
this.myContext = {
...this.myContext,
isSupported: await this.isSupportedForVKYC(),
};
const windowValues = window.location;
this.navigateOptions();
if (
windowValues.pathname.includes("product") &&
windowValues.search != ""
) {
fetchUrl(windowValues, this.props);
}
this.setState({
workingtime: true,
});
this.interval = setInterval(() => this.timer(windowValues), 5000);
let machine = null;
if (Platform.OS === 'web') {
machine = sessionStorage.getItem('machine');
}
if (machine) {
this.setState({ machine: true })
}
}
componentWillUnmount() {
clearInterval(this.interval);
}
timer = (windowValues) => {
if (
windowValues.hostname != "localhost" &&
this.state.workingtime &&
!(this.workingTime >= 6 && this.workingTime < 23)
) {
this.setState({
workingtime: true,
});
this.interval = setInterval(() => this.timer(windowValues), 5000);
}
};
navigateOptions() {
const { history } = this.props;
if (
window.location.pathname ===
`${"/" + injectUrlPaths(window.location).path + "/"}`
) {
history.push(`${"/" + injectUrlPaths(window.location).path + ""}`);
}
}
refresh() {
let clear = [
"time",
"product_name",
"payment_gateway",
"stopwatch",
"credit_opted",
"flow",
"easyPay",
"token",
];
clear.forEach((item) => {
sessionStorage.removeItem(item);
});
}
handleKeyPress = (event) => {
if (this.state.userIdle && event.keyCode === 9) {
event.preventDefault();
}
};
closebootbox = () => {
if (this.state.userIdle) {
this.refresh();
window.removeEventListener("keydown", this.handleKeyPress);
Linking.openURL(window.location.origin);
} else {
this.setState({
openmodel: false,
modalopenhide: false,
});
}
};
onIdle = async () => {
const pathName = window.location.pathname;
window.addEventListener('keydown', this.handleKeyPress);
let ExternalFlag = (Platform.OS === "web") ? sessionStorage.getItem("ExternalFlag") : await AsyncStorage.getItem("ExternalFlag");
const { history } = this.props;
let newProps = this.props.location.state;
newProps = { ...newProps, idle: true };
let redirectPath = "/servicing/index.html";
let parts = window.location.pathname.split("/");
let path = parts[parts.length - 1];
if (ExternalFlag) {
history.push({
pathname: '/servicing/redirectHome',
state: newProps
});
} else {
let machine = null;
if (Platform.OS === 'web') {
machine = sessionStorage.getItem('machine');
}
if (machine) {
window.location.href = `http://localhost:9309/SendStatus?CurrentStatus=Timeout`;
} else {
history.push({
pathname: redirectPath,
state: newProps
});
}
}
};
setTimeout = data => {
if (data.otptimer) {
this.idleTimer.pause();
} else {
this.idleTimer.resume();
}
};
clearStorage = (data) => {
data.map((item) => {
sessionStorage.removeItem(item);
});
};
render() {
const ua = window.navigator.userAgent;
return (
!this.state.isDuplicate ?
<CacheBuster enableCaching>
{({ loading, isLatestVersion, refreshCacheAndReload }) => {
if (loading) return null;
if (!loading && !isLatestVersion) {
refreshCacheAndReload();
}
return (
browserSupport(ua) && (
<LinearGradient {...this.state.linearColors}>
<IdleTimer
ref={(ref) => {
this.idleTimer = ref;
}}
element={document}
onIdle={this.onIdle}
debounce={APP.DEBOUNCE}
timeout={APP.IDLE_TIMEOUT}
/>
<View onLayout={this.handleLayout} style={styles.container}>
<script>
window.onpopstate = function() {this.props.history.go(1)};
</script>
{this.state.workingtime ? (
<AppProvider value={{ ...this.myContext, ...this.state }}>
<View style={styles.rootStyle}>
<CustomBootbox
{...this.props}
measure={this.state.measure}
bootboxtext={this.state.bootboxtext}
bootboxmodal={this.state.openmodel}
closebootbox={this.closebootbox}
hideBlackout
/>
<Routes>
{WebRoutesGenerator(
{ routeMap },
this.changeBackground
)}
</Routes>
<ModalContainer />
</View>
</AppProvider>
) : (
<AvailableTimeError
maintainanceText={this.state.maintainanceText}
/>
)}
</View>
</LinearGradient>
)
);
}}
</CacheBuster> : <View style={{ height: Dimensions.get("window").height, }}>
<View >
<Text>Previous session is already open...!</Text>
<Text><br></br> Please close the window and try again </Text>
</View>
</View>
);
}
}
export default hot((withRouter((App))))
I have a react native project and it was running in the older version of React, React Dom and rest. After updating the application to match the latest version, I am getting the above error and I couldn't find a proper solution for it.
Initially I searched withRouter imports and uses, and then created a custom hook of withRouter. Still the error persists.
import {
useLocation,
useNavigate,
useParams
} from "react-router-dom";
export function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
This issue is likely surfacing as you might be using --legacy-peer-deps flag when installing node_modules. Now Remove node_modules, and just try to fix code after doing npm install. have a nice day.

How to replace existing object in array only modifying its props and not affect to other items?

I'm trying to add item to the cart. If it is in cart, I want to replace this item with updated count and total accordingly, but I don't want to affect to other items. If it is not in cart I add it (logic of if statement). How to implement logic of else statement?
class ProductProvider extends Component {
constructor(props) {
super(props);
this.state = {
cart: [],
modalOpen: false,
modalProduct: {},
cartTotal: 0,
};
}
addToCart = (product) => {
const index = this.state.cart.findIndex((item) => item.id === product.id);
if (index === -1) {
const tempProduct = { ...product };
tempProduct.inCart = true;
tempProduct.count = 1;
const price = product.prices[0].amount;
tempProduct.total = price;
this.setState(
() => {
return { cart: [...this.state.cart, tempProduct] };
},
() => {
this.addTotal();
}
);
} else {
// solution must be here
}
};
addTotal = () => {
let total = 0;
this.state.cart.map((item) => (total += item.total));
this.setState(() => {
return {
cartTotal: parseFloat(total.toFixed(2)),
};
});
};
}
Seems like this approach, I'm currently trying to apply in other component works well. I need to test it and adapt for previous case.
constructor(props) {
super(props);
this.state = {
readMore: false,
activeID: null,
activeAtt: null,
selectedAttributes: [],
};
}
setAttributes = (name, value) => {
const index = this.state.selectedAttributes.findIndex(
(item) => item.name === name
);
if (index === -1) {
const newAttribute = { name, value };
this.setState(() => {
return {
selectedAttributes: [...this.state.selectedAttributes, newAttribute],
};
});
} else {
const tempAttributes = [...this.state.selectedAttributes];
const selectedAttribute = tempAttributes.find(
(attribute) => attribute.name === name
);
selectedAttribute.value = value;
this.setState(() => {
return { selectedAttributes: [...tempAttributes] };
});
}
else {
const tempCart = [...this.state.cart];
const selectedItem = tempCart.find((item) => item.id === product.id);
selectedItem.selectedAttributes = attributes;
selectedItem.count = selectedItem.count + 1;
const price = product.prices[0].amount;
selectedItem.total = selectedItem.total + price;
this.setState(
() => {
return { cart: [...tempCart] };
},
() => {
this.addTotal();
}
);
}

React: Play, pause onclick fuctionality

I am trying to implement play/pause on button clicking. While icons change perfectly, my actual functionality fails to work. My code is the following.
Function that is triggered on click
onPlayHandler = () => {
let aud = new Audio(this.props.data[this.state.index].audio);
aud.play();
this.setState({
isPlaying: true
});
};
onPauseHandler = () => {
let aud = new Audio(this.props.data[this.state.index].audio);
aud.pause()
//aud.setAttribute("ref", `${this.myRef}`);
this.setState({
isPlaying: false
});
//this.refs.audio.pause();
//x.pause();
//console.log(aud)
};
Button that is clicked
<Button playAudio={ this.state.isPlaying ? this.onPauseHandler : this.onPlayHandler } isPlaying={ this.state.isPlaying } />
Button component
export default function IconLabelButtons(props) {
const classes = useStyles();
return (
<>
<Button
variant="contained"
color="primary"
size="large"
className={ classes.button }
startIcon={ props.isPlaying ? <PauseIcon /> : <PlayArrowIcon /> }
onClick={ props.playAudio }
>
{ props.isPlaying ? 'Pause' : 'Play' }
</Button>
</>
);
Updated question
Entire code
import React, { Component } from 'react';
import Card from './Card';
import Button from './Button';
import correct from '../../data/media/correct.wav';
import denied from '../../data/media/denied.mp3';
var _ = require('lodash');
class AudioContainer extends Component {
constructor (props) {
super(props);
this.state = {
images: [],
index: 0,
checkedItems: new Map(),
correct: false,
isPlaying: false
};
this.audio = React.createRef();
}
componentDidMount() {
const arrImages = this.props.data.map((item) => {
let arr = [];
arr.push(item.picture);
return arr;
});
//console.log(arrImages)
this.setState({
images: _.shuffle(arrImages.flat(Infinity))
});
}
showImages = () => {
this.state.images && this.state.images.map((image) => (
<div>
<figure class="image is-128x128">
<img src={ image.src } alt="" />
</figure>
<span>{ image.name }</span>
</div>
));
};
handleChange = (e) => {
const item = e.target.name;
const isChecked = e.target.checked;
this.setState(prevState => ({ checkedItems: prevState.checkedItems.set(item, isChecked) }));
};
onCheckHandler = (e) => {
e.preventDefault();
/* function checkTrue(item) {
return item.value === true;
}
const filteredItems = this.state.checkedItems.filter(checkTrue) */
//console.log(this.state.checkedItems.value())
let arr = [];
// eslint-disable-next-line no-unused-vars
for (let [key, value] of this.state.checkedItems) {
let obj = {
value: key,
bool: value
};
arr.push(obj);
}
//console.log(arr);
let filteredArr = arr.filter((el) => {
return el.bool === true;
});
//console.log(filteredArr);
let arrWithAnswers = [];
filteredArr.map((el) => {
return arrWithAnswers.push(el.value);
});
//console.log(arrWithAnswers);
//console.log(this.props.data[this.state.index].answers.sort());
if (_.isEqual(arrWithAnswers.sort(), this.props.data[this.state.index].answers.sort())) {
let sound = new Audio(correct);
sound.play();
this.setState({
index: this.state.index + 1, checkedItems: new Map()
});
//console.log("true");
} else {
let sound = new Audio(denied);
sound.play();
}
};
update() {
const arrImages = this.props.data.map((item) => {
let arr = [];
arr.push(item.picture);
return arr;
});
//console.log(arrImages)
this.setState({
images: _.shuffle(arrImages.flat(Infinity))
});
}
onPlayHandler = () => {
let aud = new Audio(this.props.data[this.state.index].audio);
aud.play();
this.setState({
isPlaying: true
});
};
onPauseHandler = () => {
let aud = new Audio(this.props.data[this.state.index].audio);
aud.pause()
//aud.setAttribute("ref", `${this.myRef}`);
this.setState({
isPlaying: false
});
//this.refs.audio.pause();
//x.pause();
//console.log(aud)
};
render() {
//console.log(this.props.data)
//console.log(this.state.images)
//console.log(this.state.checkedItems.size);
return (
<div>
<Button playAudio={ this.state.isPlaying ? this.onPauseHandler : this.onPlayHandler } isPlaying={ this.state.isPlaying } />
<div className="columns is-vcentered is-multiline">
{ this.state.images && this.state.images.map((image, index) => (
<div className="column is-3" key={index}>
<Card image={ image.src } clickHandler={ this.handleChange } name={ image.name } />
</div>
)) }
</div>
<button className="button is-info" disabled={ this.state.checkedItems.size <= 0 } onClick={ this.onCheckHandler }>Check</button>
</div>
);
}
}
export default AudioContainer;
Your help is appreciated, thanks.
I was able to get it the way I want to, but I am not sure if it is a good practice. So what I did is the following.
let audio = new Audio()
class AudioContainer extends Component {
constructor (props) {
super(props);
this.state = {
images: [],
index: 0,
checkedItems: new Map(),
correct: false,
isPlaying: false,
error: false
};
}
onPlayHandler = () => {
audio.src = this.props.data[this.state.index].audio
audio.play();
this.setState({
isPlaying: true
});
};
onPauseHandler = () => {
audio.src = this.props.data[this.state.index].audio
//let aud = new Audio(this.props.data[this.state.index].audio);
audio.pause();
//aud.setAttribute("ref", `${this.myRef}`);
this.setState({
isPlaying: false
});
//this.refs.audio.pause();
//x.pause();
//console.log(aud)
};
I am very suspicious of declaring variable audio at the very top. So please correct me if I am wrong.

In Ant Design "Rules" in the Form.Items of Form component are not working

I am trying to use the rules in the Form. Items but because of some reason it is not supporting
NOTE: The number is not supporting but that is not an issue rules feature is not supporting at all.
NOTE: I think because it is rendering a lot that is why rules are not getting applied.
Any help to solve the issue will be great.
Here is a form component Code
import React from 'react';
import { Form, Button } from 'antd';
import { component as Template } from '#ivoyant/component-template';
class InputFormComponent extends React.Component {
state = {
formData: {},
};
enableInputFocus = (State, Props) => {
const empty = {};
const isObject = x => Object(x) === x;
const diff1 = (left = {}, right = {}, rel = 'left') =>
Object.entries(left)
.map(([k, v]) =>
isObject(v) && isObject(right[k])
? [k, diff1(v, right[k], rel)]
: right[k] !== v
? [k, { [rel]: v }]
: [k, empty]
)
.reduce(
(acc, [k, v]) => (v === empty ? acc : { ...acc, [k]: v }),
empty
);
const merge = (left = {}, right = {}) =>
Object.entries(right).reduce(
(acc, [k, v]) =>
isObject(v) && isObject(left[k])
? { ...acc, [k]: merge(left[k], v) }
: { ...acc, [k]: v },
left
);
const diff = (x = {}, y = {}) =>
merge(diff1(x, y, 'left'), diff1(y, x, 'right'));
const key = Object.keys(diff(State, Props))[0];
for (const property in Props) {
if (key == property) {
Props[property].focus = true;
} else {
Props[property].focus = false;
}
}
return Props;
};
onFinish = values => {
const { formData } = this.state;
global.console.log('Success: formData :', formData);
};
getDataFromFormItem = values => {
const { formData } = this.state;
const updatedValues = this.enableInputFocus(formData, values);
this.setState({ formData: { ...formData, ...updatedValues } });
};
onFinishFailed = errorInfo => {
global.console.log('Failed:', errorInfo);
};
render() {
const { children, properties } = this.props;
const {
submitButtonText,
formClassName,
submitButtonClassNmae,
} = properties;
const { formData } = this.state;
const childComponent = React.Children.map(children, child => {
return React.cloneElement(child, {
sendDataToForm: this.getDataFromFormItem,
updateFormData: this.updateFormData,
values: { ...formData },
});
});
return (
<div>
<Form
className={formClassName && formClassName}
onFinish={this.onFinish}
onFinishFailed={this.onFinishFailed}
>
{childComponent}
<Form.Item>
<Button
type="primary"
htmlType="submit"
className={
submitButtonClassNmae && submitButtonClassNmae
}
>
{submitButtonText && submitButtonText}
</Button>
</Form.Item>
</Form>
</div>
);
}
}
export default InputFormComponent;
Below is the code for the Input field, which is a totally different component:
import React from 'react';
import { Input, Form } from 'antd';
class InputComponent extends React.Component {
state = {
formItemData: {},
};
componentDidMount() {
const { values } = this.props;
for (const property in values) {
if (values[property].focus === true) {
this[property] && this[property].focus();
}
}
/**
* Bellow code is use when we are not passing input component as a direct child of Form component
*/
if (this.props.parentProps)
for (const property in this.props.parentProps.values) {
if (this.props.parentProps.values[property].focus === true) {
this[property] && this[property].focus();
}
}
/**
* In Bellow code true condition is exected when we are not passing input component as a direct child of Form component
*/
this.props.parentProps
? this.setState({
formItemData: { ...values, ...this.props.parentProps.values },
})
: this.setState({ formItemData: { ...values } });
}
handleOnChange = event => {
const { formItemData } = this.state;
const { id, value } = event.target;
const ID = id;
const object = {};
object[ID] = {
VALUE: value,
focus: false,
};
this.setState(
{
formItemData: { ...formItemData, ...object },
},
() => {
this.props.sendDataToForm &&
this.props.sendDataToForm(this.state.formItemData);
/**
* Bellow code is use when we are not passing input component as a direct child of Form component
*/
this.props.parentProps &&
this.props.parentProps.sendDataToForm &&
this.props.parentProps.sendDataToForm(
this.state.formItemData
);
}
);
};
render() {
const { id, className } = this.props.properties;
const { values, children } = this.props;
const { formItemData } = this.state;
const { inputFieldsConfiguration } = this.props.properties;
const childComponent = React.Children.map(children, child => {
return React.cloneElement(child, {
parentProps: { ...this.props },
});
});
return (
<div>
<div className={className && className}>
{inputFieldsConfiguration &&
// eslint-disable-next-line complexity
inputFieldsConfiguration.map(data => {
return (
<div
className={data.itemAndInputClassName}
key={data.id && data.id}
>
<div className={data.labalClassName}>
{data.label && data.label}
</div>
<Form.Item
key={data.id}
hasFeedback
name={data.id}
help={data.help && data.help}
className={
data.formItemClassName &&
data.formItemClassName
}
rules={[
{
type: "url",
}
]}
>
<Input
ref={input => {
this[data.id] = input;
}}
placeholder={
data.placeholder &&
data.placeholder
}
id={data.id && data.id}
disabled ={data.disabled && data.disabled }
value={
formItemData &&
formItemData[data.id] &&
formItemData[data.id].ID === ''
? values &&
values[data.id] &&
values[data.id].VALUE
: formItemData &&
formItemData[data.id] &&
formItemData[data.id]
.VALUE
}
className={
data.inputItemClassName &&
data.inputItemClassName
}
onChange={e =>
this.handleOnChange(e)
}
/>
</Form.Item>
</div>
);
})}
</div>
{childComponent}
</div>
);
}
}
export default InputComponent;

How to test call back refs with Enzyme and Jest

I want to test addEventListener/RemoveEventListener for an Element.
class Image extends PureComponent {
state = {
isLoaded: false,
};
componentDidMount() {
if (!this.props.src) return;
this.imageToLoad = document.createElement('img');
this.imageToLoad.addEventListener('load', this.loadImage);
this.imageToLoad.src = this.props.src;
}
componentWillUnmount() {
if (!this.imageToLoad) return;
this.imageToLoad.removeEventListener('load', this.loadImage);
}
loadImage = () => {
this.setState({ isLoaded: true }, () => {
this.myimg.src = this.imageToLoad.src;
});
}
render() {
const { className, src, alt } = this.props;
const { isLoaded } = this.state;
if (isLoaded === false || !src) return '';
return (
<img
className={className}
ref={img => (this.myimg = img)}
src={src}
alt={alt}
/>
);
}
}
Test code:-
it('should add event listener on mount', () => {
const elementMock = { addEventListener: jest.fn() };
jest.spyOn(Image.prototype, 'myimg').mockImplementation(() => elementMock);
expect(elementMock.addEventListener).toBeCalledWith('load', expect.any(Function), false);
});
But it is not working as expected.

Resources