I'm new to React hooks. Have created a small two-dropdown app. The second dropdown (DD) content is populated based on choice made from the first DD. The code I'm posting here has the first DD displaying a,b,c,d, and the second DD displaying a1 - a3, or b1 - b3, etc., depending on the choice.
First time through, everything works as expected. The glitch occurs in how the list in the second DD is displayed after changing the value in the first DD. Example: Initially choose "a" in the first DD, then "a3" in the second DD. Then go back to the first DD, and choose "b". "b1 - b4" is now displayed as expected, but "b3" is displayed at the top. I want the initial blank option to be displayed at the top every time after changing the first DD choice.
I've spent hours and hours researching this. A vanilla JS version works fine, so I'm assuming it's something I'm missing with React and perhaps hooks? Per SO and other web articles, I've tried making the DDs a 'controlled component', used multiple variations of the selected, value, and default properties on the select element, etc., etc. None of it fixes this glitch.
Thanks ahead of time to any and all who can help me understand how to fix this!
Link to codesandbox.io demo: https://codesandbox.io/s/patient-wood-0op9uu
Code below:
import React, { useEffect, useState } from 'react';
import './App.css';
function Test_1() {
const [DD1, setDD1] = useState([]);
const [DD2, setDD2] = useState([]);
useEffect(() => { }, [DD2]);
const dd_data_1 = ["a", "b", "c"];
const dd_data_2 = [{name: "a", content: "a1"}, {name: "a", content: "a2"}, {name: "a", content: "a3"},
{name: "b", content: "b1"}, {name: "b", content: "b2"}, {name: "b", content: "b3"},
{name: "c", content: "c1"}, {name: "c", content: "c2"}, {name: "c", content: "c3"}];
const zz = (e) => {
let foo = dd_data_2.filter(x => x.name === e.target.value);
setDD2(foo);
};
return (
<div id="main">
<select name="dd_1" id="dd_1" onChange={zz} >
<option value=""></option>
{dd_data_1.map((x, i) => (
<option key={i} value={x}>{x}</option>
))}
</select>
<select name="dd_2" id="dd_2">
<option value=""></option>
{DD2.map((x, i) => (
<option key={i} value={x.content}>{x.content}</option>
))}
</select>
</div>
)}
export default Test_1;
CodePudding user response:
It's not working because you set key
of option by index
of DD2 array
{DD2.map((x, i) => (
<option key={i} value={x.content}>{x.content}</option>
))}
so when your DD2 array change, the option still be the same because it have the same key. So just change your key to something unique to identifies the items in the list
{DD2.map((x, i) => (
<option key={x.content} value={x.content}>
{x.content}
</option>
))}