React-Select: Page turns white after selecting an option - reactjs

I am pretty new to React and am trying to use React-Select for a simple dropdown menu.
When you selected an option it should display the value under it, for that I'm using the onChange function and the useState Hook, but everytime I select something, the whole page just turns white.
App.js
import "./App.css";
import Select from "react-select";
import { useState } from "react";
function App() {
const [selected, setSelected] = useState(0);
const options = [
{ value: "1", label: "a" },
{ value: "2", label: "b" },
{ value: "3", label: "c" },
];
return (
<div>
<Select placeholder="Choose one"
defaultValue={selected}
onChange={setSelected}
options={options}
/>
<h1>{selected}</h1>
</div>
);
}
export default App;
Any help is appreciated, thank you.

I've done a simple edit on your code:
When onChange fires you set the selected value with onChange={(e)=>setSelected(e.value)}
Here's a functional codesandbox.

If you inspect your console in the browser, you'll see the issue is coming from the h1 component. This is probably what you're trying to achieve:
<h1>{selected.value}</h1>

I found a way to solve this, however I don't know if this is the best solution.
I created a function handleChange
const handleChange = e => {
setSelected(e.value);
}
and added a value prop, and called the function with onChange
<Select placeholder="Choose one"
defaultValue={selected}
value={options.find(obj => obj.value === selected)}
onChange={handleChange}
options={options}
/>
I don't know why
<h1>{selected.value}<h1>
doesn't work, since it's practically the same what I'm doing in handleChange, right?

Related

How can I do to select only one item in my react-multi-select-component?

I would like to choose only one option in my react-multi-select-component. Usually with other libraries I use isOptionDisabled but with that library the attribute is not valid.
Here is my code :
import React, { useState } from "react";
import ReactDOM from "react-dom";
import MultiSelect from "react-multi-select-component";
import "./styles.css";
const App = () => {
const options = [
{ label: "Grapes 🍇", value: "grapes" },
{ label: "Mango 🥭", value: "mango" },
{ label: "Strawberry 🍓", value: "strawberry" }
];
const [selected, setSelected] = useState([]);
return (
<div>
<MultiSelect
options={options}
selected={selected}
onChange={setSelected}
labelledBy={"Select"}
/>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
The project is there :
https://codesandbox.io/s/react-multi-select-component-example-forked-9xjdpr?file=/src/index.js:0-666
My problem is that I am allowed to select multiple options and I want to be restricted to selecting only one of them.
Thank you very much for your help !
As i’ve just saw from the npm doc of react-multi-select-component, that you can add the attribute hasSelectAll and set the value to false.
After the first step, the only way that i’ve found throught the API, is to add a logic with the isCreatable attribute.
react-multi-select-component
From my point of view, if you want to use a single selection, i wouldn’t rather use a multi selection library to make it a single selection, instead i would look for some library that makes my work easier.
MultiSelect react dropdown let you add a selection limit by adding selectionLimit={SELECTION_LIMIT}
So you have to add it like that:
<MultiSelect
selectionLimit={1}
options={options}
selected={selected}
onChange={setSelected}
labelledBy={"Select"}
/>
Resources
For more info about selection limit Take a look here
You can also see other useful options from the official page here

react typescript set default value multiselect

I am using this module
import { MultiSelect } from "react-multi-select-component"
and creating form by this
const [selected_to2, setSelected_to2] = useState([]);
<MultiSelect
options={options2}
value={selected_to}
onChange={setSelected_to}
labelledBy="Select2"
/>
then I creating multiselect component with default value using this
selected_to2.push({
value: item?.Code,
label: item?.Name
})
but returning value with 4 time called in the multiselect form, any proper way to set default value of multiselect then also add and remove in multiselect item?
React state must updated by set function. Edit the value directly will not work.
So you need do
setSelected_to2(s => [...s, {
value: item?.Code,
label: item?.Name
}])
First of all you are updating state is a wrong way
Wrong way
selected_to2.push({
value: item?.Code,
label: item?.Name
})
Right way:
setSelected_to2([{
value: item?.Code,
label: item?.Name
}
])
Here's a quick example that I did might help you, remember your default value must be an array of selected values since it's a multiselect component.
JSX
import { useState } from "react";
import { MultiSelect } from "react-multi-select-component";
import "./App.css";
const options = [
{ label: "The Godfather", value: 1 },
{ label: "Pulp Fiction", value: 2 },
];
const App = ({ editMode = true }) => {
const [value, setValue] = useState(editMode ? [options[1]] : []);
return (
<div className="App">
<MultiSelect
options={options}
value={value}
onChange={(selectedValues) => setValue(selectedValues)}
labelledBy="Select2"
/>
</div>
);
};
export default App;

Dropdown menu in React, filter through list

I am building a rest countries app in react and I'm trying to filter by region through a list. I would like to use a dropdown menu. I have tried using react select, creating a new component, this is my code
const DropdownMenu = (props) => {
const options = [
'', 'Africa', 'America', 'Asia', 'Europe', 'Oceania'
];
const defaultOption = options[0];
const handleFilterInput = (event) => {
let value = event.target.options;
props.handleRegionSearch(value);
};
return(
<div>
<Select options={options} onChange={handleFilterInput} value={defaultOption} placeholder="Select a region"/>
</div>
)
}
export default DropdownMenu;
My problem is, I can not get the value to change to the option selected, therefore it's impossible for me to filter the list I took from the api.
Does anyone have a possible solution for this?
Thanks
You are setting the value wrong
value={defaultOption}
This default option is never changing.
What you can do is catch the current value from onChange() and set the value somewhere (preferably in state) and then use that stored value as the value of dropdown component
Something like this.
const options = [
'', 'Africa', 'America', 'Asia', 'Europe', 'Oceania'
];
const [selectedValue , setSelectedValue ] = useState(options[0]);
const handleFilterInput = (event) => {
let value = event.target.options;
setSelectedValue(value);
props.handleRegionSearch(value);
};
return(
<div>
<Select options={options} onChange={handleFilterInput} value={selectedValue} placeholder="Select a region"/>
</div>
)
Thanks! In the end, I used a react-select component which did solve a this issue on it's own.

How do I trigger the change event on a react-select component with react-testing-library?

Given that I can't test internals directly with react-testing-library, how would I go about testing a component that uses react-select? For instance, if I have a conditional render based on the value of the react-select, which doesn't render a traditional <select/>, can I still trigger the change?
import React, { useState } from "react";
import Select from "react-select";
const options = [
{ value: "First", label: "First" },
{ value: "Second", label: "Second" },
{ value: "Third", label: "Third" },
];
function TestApp() {
const [option, setOption] = useState(null);
return (
<div>
<label htmlFor="option-select">Select Option</label>
<Select
value={option}
options={options}
onChange={option => setOption(option)}
/>
{option && <div>{option.label}</div>}
</div>
);
}
export default TestApp;
I'm not even sure what I should query for. Is it the hidden input?
My team has a test utility in our project that lets us select an item easily after spending too much time trying to figure out how to do this properly. Sharing it here to hopefully help others.
This doesn't rely on any React Select internals or mocking but does require you to have set up a <label> which has a for linking to the React Select input. It uses the label to select a given choice value just like a user would on the real page.
const KEY_DOWN = 40
// Select an item from a React Select dropdown given a label and
// choice label you wish to pick.
export async function selectItem(
container: HTMLElement,
label: string,
choice: string
): Promise<void> {
// Focus and enable the dropdown of options.
fireEvent.focus(getByLabelText(container, label))
fireEvent.keyDown(getByLabelText(container, label), {
keyCode: KEY_DOWN,
})
// Wait for the dropdown of options to be drawn.
await findByText(container, choice)
// Select the item we care about.
fireEvent.click(getByText(container, choice))
// Wait for your choice to be set as the input value.
await findByDisplayValue(container, choice)
}
It can be used like this:
it('selects an item', async () => {
const { container } = render(<MyComponent/>)
await selectItem(container, 'My label', 'value')
})
You can try the following to get it working:
Fire focus event on the ReactSelect component .react-select input element.
Fire a mouseDown event on the .react-select__control element
Fire a click on the option element that you want to select
You can add a className and classNamePrefix props with the value of "react-select" in order to specifically select the component you are trying to test.
PS: In case you are still stuck I'd encourage you to take a look at this conversation from where the above answer is borrowed - https://spectrum.chat/react-testing-library/general/testing-react-select~5857bb70-b3b9-41a7-9991-83f782377581

How to Manipulate Dropdown placeholder, onFocus?

Am new to ReactJS. I need to make the "placeholder" which is set to "State" initially to Empty/Null when onClicked or onFocus and then when it's not focused on, it goes back to "State" again. Can someone help me with this, am very new to react so any help will be appreciated.
import React from "react";
import { render } from "react-dom";
import { Container, Button, Modal, Dropdown } from "semantic-ui-react";
const stateOptions = [
{ key: "AL", value: "AL", text: "Alabama" },
{ key: "NY", value: "NY", text: "New York" }
];
const App = () => (
<Dropdown
placeholder="State"
fluid
multiple
search
selection
options={stateOptions}
/>
);
render(<App />, document.getElementById("root"));
From React's perspective, placeholder is a state that needs to be changed according to user's actions (onClick, onBlur)
So create a state to hold placeholder value that need to change.
There are two ways (since v16.8.0 with the introduction of React Hooks).
Using Class Component
class DropDown extends React.Component {
defaultPlaceholderState = "State";
state = { placeholder: this.defaultPlaceholderState };
clearPlaceholder = () => this.setState({ placeholder: "" });
resetPlaceholder = () =>
this.setState({ placeholder: this.defaultPlaceholderState });
render() {
return (
<Dropdown
onClick={this.clearPlaceholder}
onFocus={this.clearPlaceholder}
onBlur={this.resetPlaceholder}
placeholder={this.state.placeholder}
fluid
multiple
search
selection
options={stateOptions}
/>
);
}
}
In the code above, placeholder declared as a state with default value set to this.defaultPlaceholderState.
When a user clicks on the dropdown, onClick clears the placeholder value by setting it to an empty string. Same for onFocus when the Dropdown is on focus.
When a user clicks outside (onBlur), resetPlaceHolder sets the placeholder value to the default this.defaultPlaceholderState.
Using Function Component with useState hook
React v16.8.0 introduces Hooks, which enables Function Components (not a Functional Component, as it refers to Functional Programming) to hold states.
You can use React.useState hook to hold placeholder value.
const DropDownUsingHook = () => {
const defaultPlaceholderState = "State";
const [placeholder, setPlaceholder] = React.useState(defaultPlaceholderState);
const clearPlaceholder = () => setPlaceholder("");
const resetPlaceholder = () => setPlaceholder(defaultPlaceholderState);
return (
<Dropdown
onClick={clearPlaceholder}
onFocus={clearPlaceholder}
onBlur={resetPlaceholder}
placeholder={placeholder}
fluid
multiple
search
selection
options={stateOptions}
/>
);
};
⚠ Note: Unlike the Class version, clearPlaceholder, resetPlaceholder methods and placeholder state don't use this. prefix.
The implementation is similar but you use useState hook to declare the state and the setter (setPlaceholder).
Refer to the Hooks documentation, Using State Hook for more info.
You can play around with the working code on CodeSandbox.

Resources