I am using react-select library to create a multi-selection menu. When there is no value selected I want a certain style width to be used on the div and when a user starts selecting values from the select dropdown, I want this width to be set to null so that the select component can use it's own auto adjusting width capability. I have the below code but I can't get the width to update synchronously as it updates after the next render call. Not sure how to make it update with the new width immediately. I know setState is async but if you use a callback in the setState function I would imagine it would render with the new state.
...
constructor(props) {
super(props);
this.state = {
dropBoxWidth: { width: 130 },
selectLength: 1
}
}
.....
handleChange = selectedOption => {
if (this.state.selectLength > 0) {
this.setState(
{ selectedOption, selectLength: selectedOption.length, dropBoxWidth: null },
() => console.log(`Option selected:`, this.state.selectedOption, this.state.selectLength, this.state.dropBoxWidth)
);
} else {
this.setState({ dropBoxWidth: { width: 130 }, selectLength: 1 }), () =>
console.log("New Dropbox Width ", this.state.dropBoxWidth)
}
};
render() {
return (
<div style={this.state.dropBoxWidth}>
<Select
closeMenuOnSelect={false}
isMulti
options={aList}
onChange={this.handleChange}
placeholder="Item Select"
/>
</div>
)
}
Again to be clear, I want the style width of the div to be set to 130 when there is no value selected. This can be when the page is opened or refreshed(constructor props has the width to 130), and if a user selects values then decides to clear all the selections from the menu.
You can use inital state in styles of component.
<Select
options={options}
styles={{
container: (provided, state) => ({
...provided,
width: !state.hasValue && "130px",
borderBottom: "1px dotted pink"
})
}}
/>
Like here: https://codesandbox.io/s/amazing-dawn-xwcld?file=/src/App.js:290-517
React select styles doc: https://react-select.com/styles
The reason your console.log
isn't printing what you'd expect as the dropbox width is that it's not actually being passed as a callback.
If you format the setState
call a bit, you can notice that the comma is actually after the closing parenthesis:
this.setState({
dropBoxWidth: { width: 130 },
selectLength: 1
}),
() => console.log("New Dropbox Width ", this.state.dropBoxWidth);
But the issue with the code is that you're using stale data when doing the this.state.selectLength
comparison. You're not really interested in what the value was previously, but what the value is currently. The selectedOption
parameter which react-select
passes to you is either an array, or null, so you can check the length from there directly (ie instead of this.state.selectLength > 0
, you can do selectedOption && selectedOption.length > 0
).
However, since you mentioned that you're interested in the style and length because you want to style the parent div, you don't really need to store the style or the length - you can just store the selected option and derive the state in render()
:
const selectedStyle = { width: 130 }
class Selector extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedOption: null,
};
}
handleChange = (selectedOption) => {
// null or object array
this.setState({ selectedOption });
};
render() {
const { selectedOption } = this.state;
const anythingSelected = selectedOption && selectedOption.length > 0;
return (
<div style={!anythingSelected ? selectedStyle : null}>
<Select
closeMenuOnSelect={false}
isMulti
options={aList}
onChange={this.handleChange}
placeholder="Item Select"
/>
</div>
);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.