Rerender select element with a default option from parent state in React - javascript

I have a select component, which calls a callback given by a parent component to change a state maintained by the parent. This callback is called when an option is selected in the component. This select component disappears (rendering null instead of the component) after some scrolling interaction. The problem is, when the select component is allowed to reappear, it defaults to its first option, instead of the state from the parent.
I have already passed the state down to the component. I'm stuck with using the state to make an option tag of the component be selected by default once it reappears.
Here is the select component:
export default function Child({onStateChange, parentState}) {
return (
<div
...
onChange={(e) => props.onStateChange(selectEventToString(e))}
>
<select>
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
...
);
}
Here is the parent component:
export default function Parent() {
const [maintainedState, setMaintainedState] = useState("initial state");
function handleStateChange(newValue) {
setMaintainedState(newValue);
}
return (
<div className="one-town">
<Child parentState={maintainedState} onStateChange={handleStateChange} />
</div>
);
}
`
``

Try this, put your stat in value to be selected and on change select change state
const Child = ({ onStateChange, parentState }) => {
return (
<div>
<select value={parentState} onChange={e => onStateChange(e.target.value)}>
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</select>
</div>
);
};
const Parent = () => {
const [maintainedState, setMaintainedState] = useState('b');
function handleStateChange(newValue) {
setMaintainedState(newValue);
}
return (
<div className="one-town">
<Child parentState={maintainedState} onStateChange={handleStateChange} />
</div>
);
};

Related

How to capture when dropdown is open on React

Is there a way to tell when the dropdown is open and also closed? onfocus and onblur doesn't seem to be working.
<div className="select-container">
<select>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</div
You should use useState to keep track of the dropdown status. It would look something like this:
import "./styles.css";
import { useState } from "react";
export default function App() {
const [isDropDownOpen, setDropDownOpen] = useState(false);
let options = [
{
label: "money"
}
];
const handleSelect = () => {
setDropDownOpen(!isDropDownOpen);
};
const handleBlur = () => {
setDropDownOpen(!isDropDownOpen);
};
console.log(isDropDownOpen);
return (
<div>
<select onBlur={handleBlur} onClick={handleSelect}>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</div>
);
}
I have tied it into the handleSelect function, which will probably do more than just keep track of whether or not the dropdown is open but either way, it works as a reference point for now.
EDIT: Also, in case you click outside the dropdown, I used onBlur, which is controlled by handleBlur to change the boolean value because obviously, the dropdown will close.
Check the console.log on the this code sandbox to see how it works: https://codesandbox.io/s/amazing-easley-0mf7o3?file=/src/App.js

Select Dropdown not Passing Selected Values to Array in React

I am building a dropdown menu in React using a select dropdown.
or some reason, my selected value is not passing, it is passing the entire array instead of the value I selected on the dropdown.
What am I doing wrong here and how can I pass the value that I selected via dropdown?
Dropdown Code in React
<select
className='add-cap-select'
onChange={(value) => handleChangeForm('agent', value)}
>
{agents.map((agent) => (
<option id='agent' key={agent} value={form.agent}>
{agent}
</option>
))}
</select>
/**
* Handles when the user changes any regular form entry
* #param {String} prop
* #param {String} value
*/
const handleChangeForm = (prop, value) => {
setForm({
...form,
[prop]: value
})
}
Here is my simple solution to do this
import React, {useState} from 'react';
export function App(props) {
const [agent, setAgent] = useState({
agent:'',
});
const handleChangeForm = event =>{
console.log(event.target.name, event.target.value)
setAgent({...agent,[event.target.name]:event.target.value})
}
return (
<select
className='add-cap-select'
name="agent"
onChange={(event) => handleChangeForm(event)}
>
<option value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
);
}
you are passing agent and value both in handleFormChange, instead of this you can put the name in select, and from the event, you can get the name as well as value, here you are directly passing value which is event actually if you want to do in your solution then you can do like this -> value.target.value

how to send to other component onChange select in react

i just try to do something like that (when user select, continue to other component):
render() {
return(
<select onChange={(e)=> <CountrySelected countrySelected=
{e.target.value}/> }>
{this.state.countryArray.map( (e) => <option> {e.name} </option>) }
</select>
);
}
just if i can't do it, so pls continue reading the next code to tell me how can i solve the follow problem:
The following code work well for me:
class App extends Component {
state = {
countryArray: [],
selectedCountry: undefined
};
constructor(p) {
super(p);
// here i'm Initializing the this.state.countryArray
}
countrySelectionHandler=(countryName)=> {
this.setState({ selectedCountry:
this.state.countryArray.find(e=>e.name===countryName) });
}
render() {
return (
<div>
<CountryDropDown
countryArray={this.state.countryArray}
countrySelectionHandler={this.countrySelectionHandler} />
{
this.state.selectedCountry ?
// this component just display on the screen the selectedCountry name
<CountryName countryName={this.state.selectedCountry.name} />
:
<div> no country selected</div>
}
</div>
);
}
}
'CountryDropDown' component:
const countryDropDown = (p)=>(
<select onChange={(e)=> p.countrySelectionHandler(e.target.value)}>
{p.countryArray.map( (e) => <option> {e.name}
</option>) }
</select>
)
but now when user select, it's will rerender 'CountryDropDown' components for no reason.
so how can i tel react to rerender only this part:
{
this.state.selectedCountry ?
// this component just display the selectedCountry name
<CountryName countryName={this.state.selectedCountry.name} />
:
<div> no country selected</div>
}
so the way i try to solve it:
when user select, continue to other components(CountrySelected) and there render only 'CountryName' component
If you do not use PureComponent or custom shouldComponentUpdate lifecycle function.
Children component will be re-rendered when parent component re-render.
class CountryDropDown extends Component {
shouldComponentUpdate(nextProps) {
return (this.props.countryArray !== nextProps.countryArray)
}
render() {
const { countrySelectionHandler, countryArray } = this.props
return (
<select onChange={countrySelectionHandler}>
{countryArray.map((e) => <option> {e.name}
</option>)}
</select>
)
}
}
PureComponent
class CountryDropDown extends PureComponent {
render() {
const { countrySelectionHandler, countryArray } = this.props
return (
<select onChange={countrySelectionHandler}>
{countryArray.map((e) => <option> {e.name}
</option>)}
</select>
)
}
}
PureComponent has shallow compare shouldComponentUpdate function by default.

React: Can't select dropdown menu options after assigning value attribute to component's state

I have a React component that renders a dropdown menu.The component's state is updated when it receives props from its parent. I've set the 'value' attribute of the <'select> element to the state so that it re-renders when new props are received. This successfully re-renders the value in the dropdown menu when props are received but disables it from selecting a different option.
<select
type="text"
name="dogOwnerType"
id="dogOwnerType"
className="form-control"
data-bv-field="dogOwnerType"
value={this.state.dogOwnerType.ownerType}
>
<option value="">Choose Owner Type</option>
<option value="DogLover">DogLover</option>
<option value="DogOwner">DogOwner</option>
</select>
To be able to change the value; you should add an onChange handler, which sets the new value to the state.
// define function which sets new value to state
updateOwnerType = event => {
this.setState({
dogOwnerType: {
...this.state.dogOwnerType,
ownerType: event.target.value,
})
}
{/* add your onChange handler to select element */}
<select
type="text"
name="dogOwnerType"
id="dogOwnerType"
className="form-control"
data-bv-field="dogOwnerType"
onChange={this.updateOwnerType}
value={this.state.dogOwnerType.ownerType}
>

Why does setting true/false value does not work for React states?

I created a dropdown menu for sorting options with react.js but I realized that changing boolean values on React states is not valid.
<div className="Sort">
Sort by
<select
value={this.state.selectValue}
onChange={this.sorting}
>
<option value="index">Pokedex Index</option>
<option value="ascecnding">Ascending</option>
<option value="descending">Descending</option>
</select>
</div>
Here is my drop down, and it calls this function when an option is selected
sorting(e) {
if(e.target.value == "index") {
this.setState({
indexSort : !this.state.indexSort,
ascendSort: !this.state.ascendSort,
descendSort: !this.state.descendSort
});
} else if(e.target.value =="ascecnding") {
this.setState({
indexSort : !this.state.indexSort,
ascendSort: !this.state.ascendSort,
descendSort: !this.state.descendSort
});
} else {
this.setState({
indexSort : !this.state.indexSort,
ascendSort: !this.state.ascendSort,
descendSort: !this.state.descendSort
});
}
}
Is looks very ugly because I cannot directly set like indexSort: false.
Is there a better way to do this?
Instead of having three different indicators and turning them on and off I think you should rather have one single source of truth and change only that value.
Your <select>'s value is derived from the state's selectValue, so that's the only value you need to change. The other three state properties (indexSort, ascendSort and descendSort) are unnecessary.
Live example: https://codesandbox.io/s/lxqm8wqj5z
import React, { Component} from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor(props) {
super(props)
this.state = {
selectValue: 'index'
}
this.sorting = this.sorting.bind(this);
}
sorting(e) {
this.setState({ selectValue: e.target.value}, function(){
// see how the state has changed
// running inside setState's callback,
// otherwise you don't get the real state
// due to the normal (expected) delay
console.log(this.state.selectValue)
})
}
render() {
return (
<div>
<div className="Sort">
Sort by
<select value={this.state.selectValue}onChange={this.sorting}>
<option value="index">Pokedex Index</option>
<option value="ascending">Ascending</option>
<option value="descending">Descending</option>
</select>
</div>
</div>
)
}
}
render(<App />, document.getElementById('root'));

Categories

Resources