how to set value in dropdown in react js? - javascript

could you please tell me how to set value in dropdown in react js ?
I am getting dropdown data after few seconds 3000 and then I need to set value on dropdown
const App = ({ children }) => {
const val = "ax";
const [state, setState] = useState([]);
setTimeout(() => {
setState(countryOptions);
}, 2000);
return (
<Container style={{ margin: 20 }}>
<Example countryOptions={state} />
</Container>
);
};
https://codesandbox.io/s/semantic-ui-example-utev4
expected output
Aland Islands should be selected.
{ key: "ax", value: "ax", text: "Aland Islands" },
as after three second I want to select this element
const val = "ax";

As stavros answer suggested; it may be better to keep state in App component and pass the setVal to the dropdown:
App:
const App = ({ children }) => {
const [state, setState] = useState([]);
//added val and setVal in App state
const [val,setVal]=useState('ax');
setTimeout(() => {
setState(countryOptions);
}, 2000);
return (
<Container style={{ margin: 20 }}>
//pass val and setVal so dropdown can set val on change
<Example countryOptions={state} val={val} onChange={setVal}/>
</Container>
);
};
Dropdown:
const DropdownExampleClearableMultiple = ({ countryOptions,val,onChange }) => (
<Dropdown
clearable
fluid
search
closeOnChange
selection
options={countryOptions}
//set value to passed in val
value={val}
//use setVal that was passed in as onChange
onChange={(_,i)=>onChange(i.value)}
placeholder="Select Country"
/>
);

You should update your question because only after visiting the codesandbox was I able to get enough info for an answer..
In your index.js you should update setState(countryOptions) to :
setState({countryOptions:countryOptions},()=>setState({val:"ax"})
Then line 39 to :
<Example countryOptions={state.countryOptions:countryOptions} val={state.val} />
Then in your example.js update const DropdownExampleClearableMultiple to:
const DropdownExampleClearableMultiple = ({ countryOptions, val }) => (
<Dropdown
clearable
fluid
search
closeOnChange
selection
options={countryOptions}
placeholder="Select Country"
value={val}
/>
);

Use the "value" prop.
// index.js
const App = ({ children }) => {
const val = "ax";
const [state, setState] = useState([]);
setTimeout(() => {
setState(countryOptions);
}, 2000);
return (
<Container style={{ margin: 20 }}>
<Example countryOptions={state} value={val} />
</Container>
);
};
// example.js
const DropdownExampleClearableMultiple = ({ countryOptions, value }) => (
<Dropdown
clearable
fluid
search
closeOnChange
selection
value={value}
options={countryOptions}
placeholder="Select Country"
/>
);

You can pass value to value property of Dropdown. Use state property for selected value.
Make sure that you change/update state on onchange event.

Related

Setting the values of an object in an array in React?

I am building a swipeable card in React. The card contains 4 slides. The values displayed in the card rely on the user input.
First I am defining a sample object like this:
const initialState = { id: '', title: '', name: '', image: ''};
Inside my component, I am defining the array state like:
const [card, setCard] = useState([initialState]);
I am displaying the card side by side along with the user input fields for users to view the cards as they compose. So whenever the user adds/edits a specific value of the card he can view it live on the card.
We can set the state of an object for each field like this:
<Input id='title' name='title' placeholder="Enter Title" type='text' value={card.title} onChange={handleChange}/>
Handle Change function:
const handleChange = (e) => {
setCard({ ...card, [e.target.name]: e.target.value });
}
But this is not possible for the above-mentioned array of objects. So how to handle this situation?
Whenever a user swipes the previous/next card the fields must be populated with the appropriate values so that he can edit them. Simply, a user must be able to edit any field at any time. Whenever a user adds a new card a new object must be pushed to the array state.
Full code:
const initialState = { id: '', title: '', name: '', image: ''};
const Home = () => {
const [card, setCard] = useState([initialState]);
const isdisabled = true;
const handleChange = (e) => {
setCard({ ...card, [e.target.name]: e.target.value });
}
const handleAdd = () => {
//TODO
}
return (
<Flex>
<Center>
<Flex bg="white" w="lg" h="420" borderRadius="lg" m="7" p="2" alignItems="center">
<Box w="48" align="center">
<IconButton aria-label='Go to previous' disabled borderRadius="full" bg='gray.200' color='black' icon={<ChevronLeftIcon w={6} h={6}/>} />
</Box>
<Box>
<Image src={card[0].image} w="full" h="44" objectFit="cover" objectPosition="0 0" borderRadius="lg" />
<Heading color="black" size='lg'>{card[0].title}</Heading>
<Text color="black" size='40'>{card[0].namee}</Text>
</Box>
<Box w="48" align="center">
<IconButton aria-label='Go to previous' disabled borderRadius="full" bg='gray.200' color='black' icon={<ChevronRightIcon w={6} h={6}/>} />
</Box>
</Flex>
</Center>
<Flex direction="column" w="lg" gap="4" m="7">
<Input placeholder="Enter Title" value={card[0].title} onChange={handleChange}/>
<Input placeholder="Enter Name" value={card[0].name} onChange={handleChange}/>
<Button onClick={handleClick}>Upload Image</Button>
<Button onClick={handleAdd}>Add another slide</Button>
<Button colorScheme="blue">Done</Button>
</Flex>
</Flex>
)
}
export default Home
How to seamlessly do this? Any help would be appreciated. Thank you.
your card state is array of objects need to update array first object
const handleChange = (e) => {
const arr = [...card]
arr[0] = {...arr[0], [e.target.name]: e.target.value }
setCard(arr);
}
#Gabriele Petrioli's answer is the perfect solution to my problem except it needs a little tweaking:
Add activeCardIndex to both navigation handlers' dependency list:
const handleGotoNext = useCallback(() => {
// you need to also handle not allowing to go beyond the max
if(activeCardIndex < cards.length-1){
setActiveCardIndex(prevActive => prevActive + 1);
}
}, [activeCardIndex]);
const handleGotoPrevious = useCallback(() => {
// you need to also handle not allowing to go below 0
if(activeCardIndex > 0){
setActiveCardIndex(prevActive => prevActive - 1);
}
}, [activeCardIndex]);
And the handleChange function:
const handleChange = useCallback((e) => {
setCards(prevCards => prevCards.map((card, index) => {
if (index === activeCardIndex) {
return { ...card,
[e.target.name]: e.target.value
}
}else {
return card;
}
}));
}, [activeCardIndex]);
You would likely need an additional state variable, specifying the active card
something like
const [cards, setCards] = useState([initialState]);
const [activeCardIndex, setActiveCardIndex] = useState(0);
handleGotoNext = useCallback(() => {
// you need to also handle not allowing to go beyond the max
setActiveCardIndex(prevActive => prevActive + 1);
}, []);
const handleGotoPrevious = useCallback(() => {
// you need to also handle not allowing to go below 0
setActiveCardIndex(prevActive => prevActive - 1);
}, []);
const handleChange = useCallback((e) => {
setCards(prevCards => prevCards.map((card, index) => {
if (index === activeCardIndex) {
return { ...card,
[e.target.name]: e.target.value
}
}
return card;
}));
}, [activeCardIndex]);
const handleAdd = useCallback(() => {
const newCards = [...cards, { ...initialState
}];
setCards(newCards);
setActiveCardIndex(newCards.length - 1);
}, [cards]);
const activeCard = cards[activeCardIndex];
// for the rendering you should use the activeCard constant, instead of cards[n]
return (
<Flex>
...
<Image src={activeCard.image} w="full" h="44" objectFit="cover" objectPosition="0 0" borderRadius="lg" />
...
</Flex>
)

Reset Value Problem on Chakra UI's Select Component

I've a problem about Chakra UI's select component. It's somehow doesn't reset their value. Also, when I press the button, Select component doesn't render with new value
https://codesandbox.io/s/compassionate-shockley-f9chz?file=/src/app.tsx:518-863
export const App = (): JSX.Element => {
const [value, setValue] = React.useState("in");
const onClick = () => {
setValue(null);
};
console.log("App value", value);
return (
<div>
<Select options={selectionOptions} value={value} />
<Button onClick={onClick}> click </Button>
</div>
);
};
const [value, setValue] = useState(propValue);
useEffect(() => {
if (handleChange) {
handleChange(value);
}
}, [handleChange, value, setValue]);
<Select
{...rest}
value={value}
onChange={(event) => {
setValue(event?.target?.value);
}}
>
{options.map(({ value: currentValue, name }, index) => (
<option key={index} value={currentValue}>
{name}
</option>
))}
</Select>
Bumped into the exact problem. I fixed it by resetting the value with setValue("") instead of setValue(null).

React Hook Form with AsyncSelect from React-Select

working on an issue with the react-select AsyncSelect component that loads options from an API.But I can't pass the information to React-Hook Form through the controller.AsyncSelect works perfectly. The data goes back well in my "SelelectedValue" state. Can anyone help me ?
const [inputValue, setValue] = useState('');
const [selectedValue, setSelectedValue] = useState(null);
// handle input change event
const handleInputChange = value => {
setValue(value);
};
// handle selection
const handleChange = value => {
setSelectedValue(value);
}
const loadOptions = async (inputValue, callback) => {
const response = await fetch(`APIurl`);
const json = await response.json();
const object = json.records;
callback(object.map(i => ({ label: `${i.fields.firstName} - ${i.fields.lasName} , value: i.fields.firstName })))
}
<Controller
name="company"
control={control}
rules={{ required: true }}
render={({ field: { onChange, value } }) => (
<AsyncSelect
isClearable
value={selectedValue}
placeholder={'Your information'}
loadOptions={loadOptions}
onInputChange={handleInputChange}
onChange={handleChange}
styles={customStyles}
/>)}
/>
react-hook-form manages some common event and state (like value, onChange, onBlur etc.) for you so there is no need to define your own state in most case except onInputChange in AsyncSelect.
You can try to select the option and submit the form.
<Controller
name="company"
control={control}
rules={{ required: true }}
render={({ field }) => (
<AsyncSelect
{...field}
isClearable
defaultOptions
placeholder={"Your information"}
loadOptions={loadOptions}
onInputChange={handleInputChange}
// styles={customStyles}
/>
)}
/>
Here is the codesandbox

ReactJS Custom Hook not rendering the expected output

I am experimenting with ReactJS custom Hooks, but I don't understand what's happening in the example below!
I expect to see on the screen: 'Label: <followed by one of the selected option ("Bananas" or "Apples" or "Oranges")>', but it is 'Label: ' so the optionis undefined!
Could someone explain me what's happening under the hood, why I cannot see the expected output for the option ?
const useFruit = () => {
const [option, setOption] = useState<string>();
const [options] = useState(["Bananas", "Apples", "Oranges"]);
return {
option,
setOption,
options,
};
};
const FruitDropdown = () => {
const { options, setOption } = useFruit();
return (
<select
placeholder="Select option"
onChange={(e) => {
setOption(e.target.value);
}}
>
{options.map((option) => (
<option value={option}>{option}</option>
))}
</select>
);
};
const FruitLabel = () => {
const { option } = useFruit();
return (
<label>Label: {option}</label>
);
};
export default function play() {
return (
<>
<FruitDropdown />
<FruitLabel />
</>
);
}
Just because they are using the same custom hook, they are not automatically sharing state. Every time you run useFruits you will create a new isolated state which is only accessable in that instance how the hook. And whenever a the state is created it defaults to undefined.
What you need in order to solve your problem is to wrap your components inside a context and place the state inside the context. Something like this:
const FruitContext = createContext()
const FruitProvider = ({ children }) => {
const [option, setOption] = useState<string>();
const [options] = useState(["Bananas", "Apples", "Oranges"]);
return (
<FruitContext.Provider value={{ option, setOption, options }}>{children}</FruitContext.Provider>
)
}
export const useFruits = () => useContext(FruitContext)
Dont forget to wrap your components:
<FruitProvider>
<FruitDropdown />
<FruitLabel />
</FruitProvider>

Passing a prop into a custom component

I have a custom component of
const Search = (props) => {
const { type: TYPE, name: NAME, label: LABEL, onSelect, filter, value } = props;
const [data, setData] = useState([]);
const [select, setSelect] = useState(value || -1);
const applyFilter = (data) => {
let result = data;
if (filter) {
result = filter(data);
}
return result;
};
useEffect(() => {
getLookupData(TYPE)
.then((response) => {
setData(response);
})
.catch((error) => {
if (error === HttpStatus.NOT_FOUND) {
setData([]);
} else {
throw error;
}
});
}, [TYPE]);
useEffect(() => {
if (value) {
setSelect(value);
}
}, [value]);
const options = applyFilter(data).map((item) => (
<MenuItem value={item.id} key={item.id}>
{item[NAME]}
</MenuItem>
));
const handleChange = (event) => {
setSelect(event.target.value);
onSelect && onSelect(event);
};
const { classes } = props;
const labelProps = { ...(props.required && { required: props.required }) };
return (
<FormControl className={classes.formControl} id={NAME} error={props.error}>
<FormControlLabel control={<InputLabel htmlFor={NAME} {...labelProps}>{LABEL}</InputLabel>} />
<Select
name={TYPE}
value={select}
onChange={handleChange}
disabled={props.disabled || options.length === 0}
input={<Input name={TYPE} id={NAME} />}
>
<MenuItem value=''>
<em>None</em>
</MenuItem>
{options}
</Select>
</FormControl>
);
};
It takes in a menu item by default of None, however i want to pass this None menuitem as a prop and call it when i want too, as for some fields i want the option of 'none' and for some fields i do not want the option of none, currently the system is hard coded to have none appear on every drop down and i dont wish for this to happen
<Search
required
type="contractOptionToExtend"
name="optionToExtend"
label="Option To Extend"
id="contractOptionToExtend"
onSelect={change.bind(null, 'contractOptionToExtend')}
error={touched.contractOptionToExtend && Boolean(errors.contractOptionToExtend)}
value={values.contractOptionToExtend}
/>
On the above field i want to say wether or not i want the None option, I can solve this by passing it as a prop to the Search component but im not totally sure how, I have done something similar for props.required as you can see but currently i cannot do the same for the menu item.
{props.showNone
? <MenuItem value=''>
<em>None</em>
</MenuItem>
: null
}
then within the desired field
showNone={true}
credit to #Abhey Sehgal

Categories