Redux Range Selector - reactjs

I'm trying to make something like this using Redux Form:
Age range selector
The problem is that i have the field age. And I can't get it to have both values (it only stores one value)
let options = [1,2,3,4,5,6,7]; // etc... a lot of ages
// field is a redux field
// Minimum
<select {...age} value={age|| 'select'} multi={true}>
<option key='default' value='default'>Select</option>
{
options.map(option =>
<option key={option}>{option}</option>
)
}
</select>
// Maximum
<select {...age} value={age|| 'select'} multi={true}>
<option key='default' value='default'>Select</option>
{
options.map(option =>
<option key={option}>{option}</option>
)
}
</select>
I don't want to do this:
let options = [1,2,3,4,5,6,7]; // etc... a lot of ages
// field is a redux field
// Minimum
<select {...minimumAge} value={minimumAge|| 'select'} multi={true}>
<option key='default' value='default'>Select</option>
{
options.map(option =>
<option key={option}>{option}</option>
)
}
</select>
// Maximum
<select {...maximumAge} value={maximumAge|| 'select'} multi={true}>
<option key='default' value='default'>Select</option>
{
options.map(option =>
<option key={option}>{option}</option>
)
}
</select>

Would it be an option to create a component which you use multiple times?
// SelectComponent
const { options, field } = this.props;
<select {...field} value={field.value || 'select'} multi={true}>
<option key='default' value="select">Select</option>
{
options.map(option =>
<option key={option}>{option}</option>
)
}
</select>
Then use them like this:
const ages = [ 1, 2, 3, 4, 5, 6, 7 ];
<SelectComponent options={ages} field={minAge} />
<SelectComponent options={ages} field={maxAge} />
If you want to save multiple values in your Redux state you would need 2 places in your state anyway.

Related

How to have second dropdown menu values be dependent on value of first dropdown menu in React render function

In the render function of a React component, I have the following code
<select name="env" id="env">
<option value="Dev">Dev</option>
<option value="Staging">Staging</option>
<option value="Prod">Prod</option>
</select>
<select name="region" id="region">
<option value="option1">op1</option>
<option value="option2">op2</option>
<option value="option3">op3</option>
<option value="option4">op4</option>
</select>
If Dev option is selected in first dropdown, there should only be op1 choice available in the 2nd dropdown. Similarly if Staging is selected, then op1, op2 and op3 are the available choices. If Prod is selected, then all 4 choices are available. How can I achieve this in React?
You should render different region options by env.
const regionsByEnv = {
Dev: ["option1"],
Staging: ["option1", "option2", "option3"],
Prod: ["option1, option2, option3, option4"],
};
const YourComponent = () => {
const [env, setEnv] = useState("");
const regionOptions = useMemo(() => {
if (!env) {
return regionsByEnv.Prod.map((option) => (
<option value={option} key={option}>
{option}
</option>
));
}
return regionsByEnv[env].map((option) => (
<option value={option} key={option}>
{option}
</option>
));
}, [env]);
return (
<>
<select
value={env}
onChange={(e) => setEnv(e.target.value)}
name="env"
id="env"
>
<option value="Dev">Dev</option>
<option value="Staging">Staging</option>
<option value="Prod">Prod</option>
</select>
<select name="region" id="region">
{regionOptions}
</select>
</>
);
};
You should filter option for select region base on selected option of select env. So you can create a state for handling value of select env
export default function App() {
const [select1, setSelect1] = useState("Dev");
const filterOption2 = allOption2.filter((i) => {
return (
(select1 === "Dev" && i.value === "option1") ||
(select1 === "Staging" && i.value !== "option4") ||
select1 === "Prod"
);
});
return (
<div className="App">
<select name="env" id="env" onChange={(e) => setSelect1(e.target.value)}>
<option value="Dev">Dev</option>
<option value="Staging">Staging</option>
<option value="Prod">Prod</option>
</select>
<select name="region" id="region">
{filterOption2.map((op) => (
<option key={select1 + op.value} value={op.value}>
{op.name}
</option>
))}
</select>
</div>
);
}
const allOption2 = [
{
name: "op1",
value: "option1"
},
{
name: "op2",
value: "option2"
},
{
name: "op3",
value: "option3"
},
{
name: "op4",
value: "option4"
}
];
You can check in my codesandbox

How can you an the values of a selector into an empty string?

I have a selector in where I take the month, year and day of birth of a person in order to register him/her in the platform. I've tried to implement a loop to get the text content of the selector. After debugging I realized that the month for example always gets replaced by the last value, no matter what I put. For example if I choose March, It change the monthOfBirth to December no matter what.
import React, {useState} from 'react'
import './signup.css'
import axios from 'axios'
function Signup() {
const [useEmail, setUseEmail] = useState(true)
const [username, setUsername] = useState('')
const [email, setEmail] = useState('')
const [phone, setPhone] = useState('')
const [password, setPassword] = useState('')
const [monthOfBirth, setMonthOfBirth] = useState('')
const toggleEmail = () => {
if(useEmail) {
setUseEmail(false)
} else {
setUseEmail(true)
}
}
const onChangeUsername = (e) => {
setUsername(e.target.value)
}
const successAlert = () => {
alert("successful")
}
const onChangeEmail = (e) => {
if(useEmail) {
setEmail(e.target.value)
} else {
setPhone(e.target.value)
}
}
const onPasswordChange = (e) => {
setPassword(e.target.value)
}
const onSubmit = (e) => {
e.preventDefault()
const users = {
username: username,
email: email,
phone: phone,
password: password,
}
axios.post('http://localhost:5000/users/add', users)
.then(res => console.log(res.data))
}
const getValues = (e) => {
for (var i = 0; i < e.target.length; i++) {
setMonthOfBirth(e.target[i].textContent)
console.log(monthOfBirth)
}
}
const getYears=(start,end)=>{
let _years=[]
for(let i=start;i<=end;i++){
_years.push(i)
}
return _years
}
let years = getYears(1901,2021)
return (
<div className="modalsignup">
<div className="modal____popupform">
<img src="https://www.freepnglogos.com/uploads/twitter-logo-png/twitter-logo-vector-png-clipart-1.png" className="twitterLogo____signup" />
<form onSubmit={onSubmit}>
<h1 className="signup_____headertext">Create your account</h1>
<input placeholder="Name" onChange={onChangeUsername} className="placeholder____divcreateaccount"/>
{useEmail ? <input placeholder="Email" onChange={onChangeEmail} className="placeholder____divcreateaccount" />: <input placeholder="Phone" onChange={onChangeEmail} className="placeholder____divcreateaccount"/>}
<div>
<button className="switcher_____button" onClick={toggleEmail}>Use {useEmail ? "phone" : "email"} instead</button>
</div>
<input placeholder="Password" onChange={onPasswordChange} className="placeholder____divcreateaccount" type="password"/>
<div>
<h4 className="birthdate____signup">Date of birth</h4>
<p className="birthdate______paragraph">This will not be shown publicly. Confirm your own age, even if this account is for a business, a pet, or something else.</p>
</div>
<div className="selector_____options">
<div>
<select onClick={getValues} className="selector_____months">
<option value="0">Month</option>
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
</div>
<div>
<select className="selector_______days">
<option value="0">Day</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</div>
<div>
<select className="selector______year">
<option>Year</option>
{years.map(get => {
return <option value={get} key={get}>{get}</option>
})}
</select>
</div>
</div>
<div>
<button className="signup_____button" onClick={successAlert}>Next</button>
</div>
</form>
</div>
</div>
)
}
export default Signup
You have some problems in your code:
You should change onClick in the select option to onChange.
Using console.log(monthOfBirth) after setMonthOfBirth(label) in getValues method is not give the correct state, because the setMonthOfBirth which created from useState hook is an async method. When it's running you can't see the actual new state in the console. For getting the correct state after setMonthOfBirth You need a callback function.
Loop through the e.target.length for getting the selected value is not correct.
You can change getValues to bellow for getting the correct result:
const getValues = (e) => {
let index = e.nativeEvent.target.selectedIndex;
let label = e.nativeEvent.target[index].text;// getting text of the month for example : December,November...
let value = e.target.value;// getting value of the month : 11,12,...
setMonthOfBirth(label);
};
Also change the select to:
<select onChange={getValues} className="selector_____months">
And for seeing the correct state you can use use-state-with-callback and define your state same as bellow:
const [monthOfBirth, setMonthOfBirth] = useStateWithCallback("", () => {
console.log(monthOfBirth);
});

How to send back a parameter to a function pass as a param in react

I am new to react.js and find it difficult to understand the parent child component communication.
I have a Stateful component, call cookpit and a Stateless component call Schedule. I am passing a change function to Schedule from cookpit as props.
state = {
schedule : [
{
id:'01',
shift:"Morning UpStairs",
Monday:'X1',
Tuesday:'',
Wednesday:'',
Thursday:'',
Friday:''
},
{
id:'02',
shift:"Morning Down Stairs",
Monday:'X2',
Tuesday:'',
Wednesday:'',
Thursday:'',
Friday:''
},
{
id:'03',
shift:"Morning Parking Lot",
Monday:'',
Tuesday:'',
Wednesday:'',
Thursday:'',
Friday:''
},
],
};
let mapSchedule = this.state.schedule.map((item,i)=>{
return <Schedule schedule={item} key={item.id} changed={(event,day)=>this.onEmpChanged(event,item.id,day)}/>
});
In Schedule component I want set values to the each day of the state object.
<Col>
<select value={props.schedule.Monday} onChange={props.changed('monday')}>
<option value=""></option>
<option value="X1">X1</option>
<option value="X2">X2</option>
<option value="X3">X3</option>
<option value="X4">X4</option>
<option value="X5">X5</option>
<option value="X6">X6</option>
<option value="X7">X7</option>
</select>
</Col>
I am trying to pass the day to the parent with the change action so that I know which date should be updated , but its not working. please correct me.
in the Parent component
changed = (day,item)=>{
console.log(item.id,day)
}
render() {
return(
<div>
{
this.state.schedule.map(item=> <Schedule schedule={item} key={item.id} changed={this.changed}/>
)
}
</div>
)
}
and in the child component
export default function Schedule(props) {
return (
<div>
<select value={props.schedule.Monday} onChange={()=>props.changed('monday',props.schedule)}>
<option value=""></option>
<option value="X1">X1</option>
<option value="X2">X2</option>
<option value="X3">X3</option>
<option value="X4">X4</option>
<option value="X5">X5</option>
<option value="X6">X6</option>
<option value="X7">X7</option>
</select>
</div>
)
}

REACTJS and ANTD: How to change form contents through <Select> option?

I am new to React and am currently using AntD in my ReactJS code. In my code, I have a select option that is supposed to change the form elements depending on what kind of form it is.
Here is my select:
<Form.Item label="Inquiry Type">
<Select>
<Option>
form 1
</Option>
<Option>
form 2
</Option>
<Option>
form 3
</Option>
</Select>
</Form.Item>
So what should happen is that when I choose Form 1, it should be able to show me all the contents of Form 1, and the same thing for Forms 2 and 3.
I am unsure about how to do this. I have read other questions but they do not answer mine.
Check this.
state = {
selectedForm: "form1"
};
changeForm = value => {
this.setState({
selectedForm: value
});
};
render() {
const { selectedForm } = this.state;
return (
<div>
<Select value={selectedForm} onChange={value => this.changeForm(value)}>
<Option value="form1">form 1</Option>
<Option value="form2">form 2</Option>
<Option value="form3">form 3</Option>
</Select>
{selectedForm === "form1" ? (
<Form1 />
) : selectedForm === "form2" ? (
<Form2 />
) : selectedForm === "form3" ? (
<Form3 />
) : ""}
</div>
);
}

Reactjs - Select box with varying first option based on passed attribute

I am trying to show the first option different based on an attribute I pass.
In the search page, I want the user to be able to select "Any" option.
In the edit profile page, "Any" option should not be shown because that is only for search.
Edit profile page
<option value="0" disabled selected>
Select Religion
</option>
Search page
<option value="Any" selected>
Any Religion
</option>
Search profile page has this code:
import React, { Component } from 'react'
..
import ReligionInput from '../edit-profile/religion-input'
..
..
<ReligionInput value={religion} change={this.changeReligion} any="Y" />
...
And ReligionInput has a check for any == Y or not but its not working and always has the Any option. What is wrong with the code below ?
import religionOptions from './religion-options'
const InputReligion = ({ value, change, any }) => (
<div className="edit_religion_div">
<Select
placeholder="Select option"
value={value}
valueChange={e => change('religion', e)}
className="edit_religion my2"
>
{any} == 'Y' ?
`<option value="Any" selected>
Any Religion
</option>` :
`<option value="0" disabled selected>
Select Religion
</option>`
{religionOptions.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>;
})}
</Select>
</div>
)
InputReligion.propTypes = {
value: PropTypes.string.isRequired,
change: PropTypes.func.isRequired,
}
All other options come from religionOptions.
A dirty way of doing it would be.
<option value={ any=='Y' ? '0' : 'Any' } selected>{ any=='Y' ? 'select' : 'any religion' }</option>
Yeah, not really a fan of those conditions either.
A cleaner and more readable approach would be:
const InputReligion = (props) => {
let defaultOption = null;
if (props.any == 'Y' ) {
defaultOption = <option value='Any' selected>Any religion</option>
} else {
defaultOption = <option value='0' selected disabled>Select Religion</option>
}
return (
<div className="edit_religion_div">
<select placeholder="Select Option"
className="edit_religion my2"
value={ props.value }
valueChange={ e => change('religion', e)}
>
{ defaultOption }
{
religion.map( (e, key) => {
return <option key={ key } value={ e.value }>{ e.name }</option>
})
}
</select>
</div>
)
}

Resources