Updating data on changedropdown in Reactjs gets delayed - javascript

I am new to ReactJS. I have created a service that I have called inside componentWillMount() since I want the data as soon as the page loads.
Now I want to use the same service when there is a dropdown change and update with the new value.
I have called the service inside onChangeDropDown() but it appears that updated value is not rendered correctly.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import config from '../../../../config';
import {
Container, Divider, Accordion, Icon, Transition, Label, Table
} from 'semantic-ui-react';
import Utilities, { Button, PtInput, PtInputShort, PtInputIcon, PtSelect, PtDateInput, PtInputConditionTab, PtInputNextToEachOther } from '../../../../grit-utilities';
import ScrollArea from 'react-scrollbar';
export default class Future extends Component {
constructor(props) {
super(props);
this.state = {
...this.props.futureModel.pavementcondition,
selectedYear: new Date().getFullYear(),
PQI: 'N.A.',
Age: 'N.A.',
Aadt: 'N.A.',
Esals: 'N.A.',
CumEsals: 'N.A.',
pqiArray: []
};
}
getYearOptions = () => {
const yearOptions = [];
for (let i = 0; i < 35; i++) {
yearOptions.push({ key: new Date().getFullYear() + i, value: new Date().getFullYear() + i, label: new Date().getFullYear() + i});
}
return yearOptions;
}
fetchProjectionData = (selectedYear) => {
axios.get(`${config.server}\\fetchFutureData\\${this.props.futureModel.route.id}\\${selectedYear}`).
then((res) => {
if (res.data.result[0]) {
let data = res.data.result[0];
this.setState({
//PQI: data.PSR,
Age: data.Age,
Esals: data.Esals,
Aadt: data.AADT,
CumEsals: data.CumEsal
});
}
});
}
render() {
const yearOptions = this.getYearOptions();
return (
<Container>
<ScrollArea
speed={1}
className={!window.mobileAndTabletcheck() ? "area_desktop" : "area_mobile"}
contentClassName="content"
smoothScrolling={true}>
<PtSelect name="selectedYear" defaultVal={this.state.selectedYear} label="Select Year" options={yearOptions} onChange={this.onChangeDropdown.bind(this)} />
<PtInput disabled placeholder="Not Available" name="PQI" value={this.state.PQI ? this.state.PQI:''} label="PQI - Pavement Quality Index" disabled name="PQI" />
<PtInput disabled placeholder="Not Available" name="Age" value={this.state.Age ? this.state.Age:''} label="Age" disabled name="Age" />
<PtInput disabled placeholder="Not Available" name="Aadt" value={this.state.Aadt ? Math.round(this.state.Aadt) : ''} label="AADT" disabled name="AADT" />
<PtInput disabled placeholder="Not Available" name="Esals" value={this.state.Esals ? Math.round(this.state.Esals):''} label="ESALs" disabled name="ESALs" />
<PtInput disabled placeholder="Not Available" name="CumEsals" value={this.state.CumEsals ? Math.round(this.state.CumEsals) : ''} label="Cumulative ESALs" disabled name="CumESALs" />
</ScrollArea>
</Container>
);
}
/* This function actually gets the PQI value for the current year based on routeId and year from FutureTabView hard table
Date: 09/25/2019
*/
getfirstPQI = () =>{
fetch(`${config.server}/getfirstpqi/`+this.props.futureModel.route.id+`/`+this.state.selectedYear)
.then(response=>response.json())
.then(data=>{
//console.log(data[0]['PSR'])
this.setState({PQI:data[0]['PSR']})
})
}
onChangeDropdown = (e) => {
const { target } = e;
const { name, value } = target;
this.setState({ [name]: parseInt(value) });
this.fetchProjectionData(value);
this.getfirstPQI();
}
componentDidMount() {
this.fetchProjectionData(this.state.selectedYear);
this.getfirstPQI();
}
}
I have done this code and what I am trying to do it as soon as the page loads it should show the value that is being received from the service. Example: the current year is 2019 and as soon as the page loads the value for the year 2019 is being rendered. Now I have a dropdown of years.So when I choose 2020 the value is not getting updated whereas when I choose 2021 it updates the value with the value of 2020. So the updating value is delaying always. How to render the value as soon as there is a change in dropdown?

React's setState() is asynchronous, meaning if you want to access the updated state after setting it then you should use the callback which runs when the state has successfully updated.
this.setState({ [name]: parseInt(value) }, () => {
this.fetchProjectionData(value);
this.getfirstPQI();
});
If you don't use the callback then getfirstPQI() may be reading the old state.

Related

how to fix Error componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops

I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.
this is the input component code Number I have tried the input component works well,:
import React from "react";
import propTypes from "prop-types";
import "./index.scss";
export default function Number(props) {
const {
value,
placeholder,
name,
min,
max,
prefix,
suffix,
isSuffixPlural,
} = props;
const onChange = (e) => {
let value = String(e.target.value);
if (+value <= max && +value >= min) {
props.onChange({
target: {
name: name,
value: +value,
},
});
}
};
const minus = () => {
value > min &&
onChange({
target: {
name: name,
value: +value - 1,
},
});
};
const plus = () => {
value < max &&
onChange({
target: {
name: name,
value: +value + 1,
},
});
};
return (
<div className={["input-number mb-3", props.outerClassName].join(" ")}>
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text minus" onClick={minus}>
-
</span>
</div>
<input
min={min}
max={max}
name={name}
pattern="[0-9]*"
className="form-control"
placeholder={placeholder ? placeholder : "0"}
value={`${prefix}${value}${suffix}${
isSuffixPlural && value > 1 ? "s" : ""
}`}
onChange={onChange}
/>
<div className="input-group-append">
<span className="input-group-text plus" onClick={plus}>
+
</span>
</div>
</div>
</div>
);
}
Number.defaultProps = {
min: 1,
max: 1,
prefix: "",
suffix: "",
};
Number.propTypes = {
value: propTypes.oneOfType([propTypes.string, propTypes.number]),
onChange: propTypes.func,
placeholder: propTypes.string,
isSuffixPlural: propTypes.bool,
outerClassName: propTypes.string,
};
and this is my input date component code I have tried the input component works well, :
import React, { useState, useRef, useEffect } from "react";
import propTypes from "prop-types";
import { DateRange } from "react-date-range";
import "./index.scss";
import "react-date-range/dist/styles.css"; // main css file
import "react-date-range/dist/theme/default.css"; // theme css file
import formatDate from "utils/formatDate";
import iconCalendar from "assets/images/icon/icon-calendar.svg";
export default function Date(props) {
const { value, placeholder, name } = props;
const [isShowed, setIsShowed] = useState(false);
const datePickerChange = (value) => {
const target = {
target: {
value: value.selection,
name: name,
},
};
props.onChange(target);
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
});
const refDate = useRef(null);
const handleClickOutside = (event) => {
if (refDate && !refDate.current.contains(event.target)) {
setIsShowed(false);
}
};
const check = (focus) => {
focus.indexOf(1) < 0 && setIsShowed(false);
};
const displayDate = `${value.startDate ? formatDate(value.startDate) : ""}${
value.endDate ? " - " + formatDate(value.endDate) : ""
}`;
return (
<div
ref={refDate}
className={["input-date mb-3", props.outerClassName].join(" ")}
>
<div className="input-group">
<div className="input-group-prepend bg-gray-900">
<span className="input-group-text">
<img src={iconCalendar} alt="icon calendar" />
</span>
</div>
<input
readOnly
type="text"
className="form-control"
value={displayDate}
placeholder={placeholder}
onClick={() => setIsShowed(!isShowed)}
/>
{isShowed && (
<div className="date-range-wrapper">
<DateRange
editableDateInputs={true}
onChange={datePickerChange}
moveRangeOnFirstSelection={false}
onRangeFocusChange={check}
ranges={[value]}
/>
</div>
)}
</div>
</div>
);
}
Date.propTypes = {
value: propTypes.object,
onChange: propTypes.func,
placeholder: propTypes.string,
outerClassName: propTypes.string,
};
I have tried the inpudate component to run well, as well as the input number, but if I combine these components I have an error did i miss something, and I tried to combine these components on the bookingform page but when I tried on the browser I experienced the above error.
My code is in the Booking Form:
import React, { Component } from "react";
import propTypes from "prop-types";
import Button from "elements/Button";
import { InputNumber, InputDate } from "elements/Form";
export default class BookingForm extends Component {
constructor(props) {
super(props);
this.state = {
data: {
duration: 1,
date: {
startDate: new Date(),
endDate: new Date(),
key: "selection",
},
},
};
}
updateData = (e) => {
this.setState({
...this.state,
data: {
...this.state.data,
[e.target.name]: e.target.value,
},
});
};
componentDidUpdate(prevProps, prevState) {
const { data } = this.state;
if (prevState.data.date !== data.date) {
const startDate = new Date(data.date.startDate);
const endDate = new Date(data.date.endDate);
const countDuration = new Date(endDate - startDate).getDate();
this.setState({
data: {
...this.state.data,
duration: countDuration,
},
});
}
if (prevState.data.duration !== data.duration) {
const startDate = new Date(data.date.startDate);
const endDate = new Date(
startDate.setDate(startDate.getDate() + +data.duration - 1)
);
this.setState({
...this.state,
data: {
...this.state.data,
date: {
...this.state.data.date,
endDate: endDate,
},
},
});
}
}
startBooking = () => {
const { data } = this.state;
this.props.startBooking({
_id: this.props.itemDetails._id,
duration: data.duration,
date: {
startDate: data.date.startDate,
endDate: data.date.endDate,
},
});
this.props.history.push("/checkout");
};
render() {
const { data } = this.state;
const { itemDetails } = this.props;
console.log(this.state);
return (
<div className="card bordered" style={{ padding: "60px 80px" }}>
<h4 className="mb-3">Start Booking</h4>
<h5 className="h2 text-teal mb-4">
${itemDetails.price}{" "}
<span className="text-gray-500 font-weight-light">
per {itemDetails.unit}
</span>
</h5>
<label htmlFor="duration">How long you will stay?</label>
<InputNumber
max={30}
suffix={" night"}
isSuffixPlural
onChange={this.updateData}
name="duration"
value={data.duration}
/>
<label htmlFor="date">Pick a date</label>
<InputDate onChange={this.updateData} name="date" value={data.date} />
<h6
className="text-gray-500 font-weight-light"
style={{ marginBottom: 40 }}
>
You will pay{" "}
<span className="text-gray-900">
${itemDetails.price * data.duration} USD
</span>{" "}
per{" "}
<span className="text-gray-900">
{data.duration} {itemDetails.unit}
</span>
</h6>
<Button
className="btn"
hasShadow
isPrimary
isBlock
onClick={this.startBooking}
>
Continue to Book
</Button>
</div>
);
}
}
BookingForm.propTypes = {
itemDetails: propTypes.object,
startBooking: propTypes.func,
};
I encountered this error and tried to fix it, but couldn't find a solution to the problem
I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.
I encountered this error and tried to fix it, but couldn't find a solution to the problem
I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.
I encountered this error and tried to fix it, but couldn't find a solution to the problem
I use react js to create a staycation website, when I want to display the InputNumber and InputDate components I experience an error like the title above, in the componentDidUpdate section, I have tried tweaking the code but it hasn't worked, but when I omit the componentDidUpdate part, the inputdate and inputnumber components run.

Make POST request and update DB for each and every user in Child Component, using React Life Cycle Method

Here Table shows the previous month user salary details. When click the "Update" button, system will retrieve the necessary data for this month and calculate the new salary and properties and will update the child component table values. Child component has other Child Component Buttons too.
When updating the table raws with new values "Need to make a post request for each and every user and update the database iterately". Here infinity looping happening(infinity POST request for update DB) when render child component and its children.
Could you please suggest a way to update each and every user details to the database. The way to call Redux action function(this.props.updateUserLog(newUserLog.handle, userDetails)) inside the child component "RowComponent". When re-rendering it's children, the POST request must not send looping.
~ Parent Component ~
import { getDriverCommissionAlcohol } from "../redux/actions/dataActions";
class DriverPerfomance extends Component {
constructor(props = {}) {
super(props);
this.state = {
press: false,
};
}
UpdatePerformance = (event) => {
this.setState({ press: true });
this.props.getDriverCommissionAlcohol(month, year);
};
render() {
const {
data: {
drivers: { user, month, year, createdAt },
performance: { driverCommission, alcoholStatus },
},
UI: { loadingOffScrean },
} = this.props;
let DriverCommissionResults = {};
if (this.state.press) {
let combinedUser = {};
let recent = [];
if (Object.keys(DriverCommissionResults).length > 0) {
combinedUser.forEach((filteredPerson) => {
recent.push(
<RowComponent
key={filteredPerson.userId}
handle={filteredPerson.username}
monthRetrive={this.state.month}
yearRetrive={this.state.year}
month={month}
year={year}
drunkenPesentage={filteredPerson.drunkenPesentage}
press={true}
newMonthCalculationDone={true}
/>
);
});
} else {
recent = (
<Fragment>
{user.map((filteredPerson) => (
<RowComponent
key={filteredPerson.userId}
handle={filteredPerson.username}
month={month}
year={year}
press={false}
newMonthCalculationDone={false}
/>
))}
</Fragment>
);
}
}
return (
<Fragment>
<Button disabled={loadingOffScrean} onClick={this.UpdatePerformance}>
Update
</Button>
<table>
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody>{recent}</tbody>
</table>
</Fragment>
);
}
}
~ Child Component ~
import { updateUserLog } from "../redux/actions/dataActions";
class RowComponent extends Component {
constructor(props) {
super(props);
this.state = {
handle: "",
createdAt: "",
ranking: 0,
year: "",
month: "",
};
}
componentWillReceiveProps() {
const newUserLog = {
handle: this.props.handle,
createdAt: new Date().toISOString(),
ranking: NewRankingCalculate,
year: this.props.yearRetrive ? this.props.yearRetrive : this.props.year,
month: this.props.monthRetrive ? this.props.monthRetrive : "",
};
this.mapUserDetailsToState(newUserLog);
}
mapUserDetailsToState = (newUserLog) => {
this.setState({
handle: newUserLog.handle ? newUserLog.handle : "",
createdAt: newUserLog.createdAt ? newUserLog.createdAt : "",
ranking: newUserLog.ranking ? newUserLog.ranking : "",
year: newUserLog.year ? newUserLog.year : "",
month: newUserLog.month ? newUserLog.month : "",
});
const userDetails = {
handle: newUserLog.handle,
createdAt: newUserLog.createdAt,
ranking: newUserLog.ranking,
year: newUserLog.year,
month: newUserLog.month,
};
this.props.updateUserLog(newUserLog.handle, userDetails);
};
render() {
const {
member: { username, year, month, salary },
} = this.props;
let action = (
<DrunkenLog
handle={username}
month={this.state.month !== "" ? this.state.month : month}
year={this.state.year !== "" ? this.state.year : year}
/>
);
<tr>
<td>{initialSalary}</td>
<td>{this.state.salary !== 0 ? this.state.salary : salary}</td>
<td>{action}</td>
</tr>;
}
}
Expectation:
Update DB table for each and every user, by calling POST requests function inside the child component life cycle methods. Stop the infinity looping POST requests. And make post request once changing the props.
i've noticed that if (Object.keys(DriverCommissionResults).length > 0) expression in ParentComponent will always be false, right? because DriverCommissionResults is just an empty object, initialised two rows before this check :)
try extend RowComponent from PureComponent, this will ensure that RowComponent will rerender only if some of props really changed (see docs: https://reactjs.org/docs/react-api.html#reactpurecomponent)
but i don't like the whole idea of what you are doing here.
You are basically change state of ParentComponent on button click, and make side effect (call redux in this case) when component is receiving props.
I would suggest:
in ParentComponent - make side effect (update DB) right in the middle of Button.onClick (keeping state changes, because you need some sort of wait indicator maybe).
in RowComponent - if you are doing some side effects - better place for them is componentDidMount or componentDidUpdate (but in second place you better always check for props to really differ from previous ones!)

React stale error date on child components

I'm trying to have form input elements, which are uncontrolled because of our use of jQuery UI DatePicker and jQuery maskMoney, render errors underneath them as soon as user types something invalid for that field, as well as disable the button on any of the errors. For some reason, none of that is working right.
Main component
is something like the following:
class MainComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
payrates: [
new PayRate(new Date(2019, 2, 1), 0.00),
],
errors : {
rate: '',
date: ''
},
currentPayRate : new PayRate() // has Rate and EffectiveDate fields
}
// binding done here
this.appendValue = this.appendValue.bind(this)
this.updateCurrentPayRate = this.updateCurrentPayRate.bind(this)
this.updateCurrentPayRateDate = this.updateCurrentPayRateDate.bind(this)
this.updateCurrentPayRateAmount = this.updateCurrentPayRateAmount.bind(this)
this.validate = this.validate.bind(this)
}
/**
* #param { PayRate } newPayRate
**/
updateCurrentPayRate(newPayRate) {
this.setState({
...this.state,
currentPayRate : newPayRate
})
}
updateCurrentPayRateDate(dateString) {
const newPayRate = Object.assign(new PayRate(), this.state.currentPayRate, { EffectiveDate : new Date(dateString) } )
this.validate(newPayRate)
this.updateCurrentPayRate(newPayRate)
}
updateCurrentPayRateAmount(amount) {
const newPayRate = Object.assign(new PayRate(), this.state.currentPayRate, { Rate : Number(amount) } )
this.validate(newPayRate)
this.updateCurrentPayRate(newPayRate)
}
/**
* #param { PayRate } value
**/
appendValue(value) {
console.log("trying to append value: ", value)
if (this.validate(value)) {
this.setState({...this.state,
payrates : this.state.payrates.concat(this.state.currentPayRate)})
}
}
/**
* #param { PayRate } value
**/
validate(value) {
// extract rate,date from value
const rate = value.Rate,
date = value.EffectiveDate
console.log("value == ", value)
let errors = {}
// rate better resolve to something
if (!rate) {
errors.rate = "Enter a valid pay rate amount"
}
// date better be valid
if ((!date) || (!date.toLocaleDateString)) {
errors.date = "Enter a date"
}
else if (date.toLocaleDateString("en-US") === "Invalid Date") {
errors.date = "Enter a valid pay rate date"
}
console.log(errors)
// update the state with the errors
this.setState({
...this.state,
errors : errors
})
const errorsToArray = Object.values(errors).filter((error) => error)
return !errorsToArray.length;
}
render() {
return <div>
<DateList dates={this.state.payrates}/>
<NewPayRateRow
value={this.state.currentPayRate}
errors={this.state.errors}
onChange={this.updateCurrentPayRate}
onPayRateAmountChange={this.updateCurrentPayRateAmount}
onPayRateDateChange={this.updateCurrentPayRateDate}
onAdd={this.appendValue}
/>
</div>
}
}
The "form" component
Has the following implementation:
class NewPayRateRow extends React.Component {
constructor(props) {
super(props)
}
render() {
console.log(Object.values(this.props.errors).filter((error) => error))
return <span class="form-inline">
<RateField
errors={this.props.errors.rate}
onKeyUp={(e) => {
// extract the value
const value = e.target.value
this.props.onPayRateAmountChange(value)
}}
/>
<DateInput
errors={this.props.errors.date}
onChange={this.props.onPayRateDateChange}
/>
<button onClick={(e) => {
this.props.onAdd(this.props.value)
}}
disabled={Object.values(this.props.errors).filter((error) => error).length}>Add New Pay Rate</button>
</span>
}
}
An uncontrolled input component
where the issue definitely happens:
class DateInput extends React.Component {
constructor(props) {
super(props);
// do bindings
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
$('#datepicker').datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true,
yearRange: "-116:+34",
dateFormat: 'mm/dd/yy',
// telling jQuery UI to pass its event to React
onSelect : this.handleChange
});
}
componentWillUnmount() {
$('#datepicker').datepicker('destroy')
}
// handles a change to the input field
handleChange(value) {
this.props.onChange(value)
}
render() {
const fieldIsInvalid = this.props.errors || ''
return <div class="col-md-2">
<input
id="datepicker"
className={"datepicker form-control " + fieldIsInvalid }
placeholder="mm/dd/yyyy"
onChange={(e) => this.props.onChange(e.target.value) }>
</input>
<div>
{this.props.errors}
</div>
</div>
}
}
For some reason, even though I'm selecting via the datepicker widget the value, the errors don't change:
However, when I go to comment out all the validate calls, it adds the fields no problem.
I did some caveman debugging on the value I was passing to validate to ensure that I was passing it truthy data.
Why is this.state.error not updating correctly, via the components?!
UPDATE: I went to update just the pay rate, initially, and the errors rendered correctly, and from going through the code, I found that this.setState was actually setting the state. However, when I went to trigger change on the input money field, this.setState was getting hit, and errors object, was empty (which is correct), but somehow, this.setState wasn't actually updating the state.
I fixed the issue!
What I did
Instead of persisting errors in the global state, and instead of passing validate, to set the global state, to the methods, I maintain it as function defined outside the main component's class, like this :
/**
* Validates a PayRate
* #param { PayRate } value
* #returns { Object } any errors
**/
function validate(value = {}) {
// extract rate,date from value
const rate = value.Rate,
date = value.EffectiveDate
let errors = {}
// rate better resolve to something
if (!rate) {
errors.rate = "Enter a valid pay rate amount"
}
// date better be valid
if ((!date) || (!date.toLocaleDateString)) {
errors.date = "Enter a date"
}
else if (date.toLocaleDateString("en-US") === "Invalid Date") {
errors.date = "Enter a valid pay rate date"
}
return errors
}
Note the much simpler implementation. I then no longer need to call validate on the updateCurrentPayRate... methods.
Instead, I invoke it on NewPayRateRow.render (which I can now do because it's not touching state at all, avoiding any invariant violation), save the result to a local const variable, called errors, and use that instead of this.props.errors. Though, truth be told, I could probably put validate back in this.props to achieve a layer of abstraction/extensibility.
Also, I took Pagoaga's advice and used className instead of class (I don't have that as muscle memory yet).
You have a "class" attribute inside several of your render functions, replacing it with "className" will allow the error to show up : https://codepen.io/BPagoaga/pen/QoMXmw
return <div className="col-md-2">

React Select disable options

I'm having issues disabling certain options within a large list within a React Select element. I have around 6,500 options that get loaded into the select. At first I was having issues with the search functionality lagging but then I started using react-select-fast-filter-options which took care of that problem. Now the issue is that I need to disable certain options depending on the propType "picks". Here is the code:
import React, {Component} from 'react'
import PropTypes from 'prop-types';
import 'react-select/dist/react-select.css'
import 'react-virtualized/styles.css'
import 'react-virtualized-select/styles.css'
import Select from 'react-virtualized-select'
import createFilterOptions from 'react-select-fast-filter-options';
let options = [];
if(typeof stockSearchStocks !== 'undefined') {
//loads in all available options from backend by laying down a static js var
options = stockSearchStocks
}
const filterOptions = createFilterOptions({options});
class StockSearch extends Component {
static propTypes = {
exchanges: PropTypes.array.isRequired,
onSelectChange: PropTypes.func.isRequired,
searchDisabled: PropTypes.bool.isRequired,
picks: PropTypes.array.isRequired,
stock_edit_to_show: PropTypes.number
}
/**
* Component Bridge Function
* #param stock_id stocks id in the database
*/
stockSearchChange = (stock_id) => {
this.props.onSelectChange(stock_id);
}
//this is my current attempt to at least
//disable options on component mount but this doesn't seem to be working
componentWillMount = () => {
console.log('picks!: ' + JSON.stringify(this.props.picks));
let pickIDs = this.props.picks.map((p) => p.stock_id);
options = options.map((o) => {
// console.log(pickIDs.indexOf(o.value));
if(pickIDs.indexOf(o.value)) {
// console.log('here is the option: ' + JSON.stringify(o));
// console.log('here is the option: ' + o.disabled);
o.disabled = true;
}
})
}
/**
* handles selected option from the stock select
* #param selectedOption
*/
handleSelect = (selectedOption) => {
this.stockSearchChange(selectedOption.value);
}
render() {
return (
<div className="stock-search-container">
<Select
name="stock-search"
options={options}
placeholder="Type or select a stock here..."
onChange={this.handleSelect}
disabled={this.props.searchDisabled}
value={this.props.stock_edit_to_show}
filterOptions={filterOptions}
/>
</div>
)
}
}
export default StockSearch;
I have tried filtering through the picks props and changing that options variable to include disabled:true but this lags the application and I'm not sure if that will work now that I'm using react-select-fast-filter-options as it seems to be doing some sort of indexing. Is there a way to filter through the options var to find all instances of the picks prop and disable those options quickly?
isDisabled={this.props.disabled}
You are passing a wrong prop.. For v2, the prop is isDisabled.
https://github.com/JedWatson/react-select/issues/145
In react-select v2:
add to your array of options a property 'disabled': 'yes' (or any other pair to identify disabled options)
use isOptionDisabled props of react-select component to filter options based on 'disabled' property
Here's an example:
import Select from 'react-select';
const options = [
{label: "one", value: 1, disabled: true},
{label: "two", value: 2}
]
render() {
<Select id={'dropdown'}
options={options}
isOptionDisabled={(option) => option.disabled}>
</Select>
}
More information about react-select props is in the docs and here's an example they reference.
use the following to disable an option.
import Select from 'react-select';
render() {
const options = [
{label: "a", value: "a", isDisabled: true},
{label: "b", value: "b"}
];
return (
<Select
name="myselect"
options={options}
</Select>
)
}
People are making it a JavaScript issue. I say make it a CSS one and simplify.
Use this
style={{display: month === '2' ? 'none' : 'block'}}
Like so...
There are only 28 days in February
const ComponentName =() => {
const [month, setMonth] = useState("")
const [day, setDay] = useState("")
return (
<>
<select
onChange={(e) => {
const selectedMonth = e.target.value;
setMonth(selectedMonth)>
<option selected disabled>Month</option>
<option value= '1'>January</option>
<option value= '2'>February</option>
</select>
<select
onChange={(e) => {
const selectedDay = e.target.value;
setDay(selectedDay)>
<option selected disabled>Day</option>
<option value= '28'>28</option>
<option value= '29' style={{display: month === '2' ? 'none' : 'block'}}>29</option>
<option value= '30'>30</option>
</select>
</>
)
}
export default ComponentName;

ReactJs Select add default value

I want to store select default value if user not touch it in ReactJs. How is that possible?
<select onChange={this.valSelected.bind(this)}>
{currencies.map(function(name, index){
return <option value={name}>{name}</option>;
})}
</select>
and
valSelected(event){
this.setState({
valSelected: event.target.value
});
}
You can just add a value property to the select element, set by your state.
<select value={this.state.valSelected} onChange={this.valSelected.bind(this)}>
{currencies.map(function(name, index){
return <option value={name}>{name}</option>;
})}
</select>
This is described here in the react docs: Doc Link
Then set a default state for the component, either in the constructor or with getInitialState: What is the difference between using constructor vs getInitialState in React / React Native?
Use defaultValue to select the default value.
const statusOptions = [
{ value: 1, label: 'Publish' },
{ value: 0, label: 'Unpublish' }
];
const [statusValue, setStatusValue] = useState('');
const handleStatusChange = e => {
setStatusValue(e.value);
}
return(
<>
<Select options={statusOptions} defaultValue={[{ value: published, label: published == 1 ? 'Publish' : 'Unpublish' }]} onChange={handleStatusChange} value={statusOptions.find(obj => obj.value === statusValue)} required />
</>
)

Categories