我有一个下拉菜单显示州和县。我要县一级依靠州一级。我正在使用react,javascript,prisma来访问数据库。我把它分开了,这样我就能让各州和各县显示出来,但我不知道如何使它们独立。我认为我需要的是一种改变我的功能的方法,它能带来县的数据。我可以根据选择的状态进行分组。所以,我需要的是在获得被选中的状态以将其发送到我的"byCounty“函数之后。这有可能吗?
menu.js
export default function DropDownMenu(props){
if(!props.states) return
return(
<table>
<body>
<select onChange={(e) => { console.log(e.target.value) }}>
{props.states.map(states=>
<option>{states.state}</option>
)}
</select>
<select >
{props.byCounty.map(byCounty=>
<option>{byCounty.county}</option>
)}
</select>
</body>
</table>
)
}functions.js
const states = await prisma.county.groupBy({
by:["state"],
where: {
date: dateTime,
},
_sum:{
cases:true,
},
});
const byCounty = await prisma.county.groupBy({
by:["county"],
where: {
date: dateTime,
state: 'THIS SHOULD BE THE STATE NAME SELECTED BY USER'
},
_sum:{
cases:true,
},
});
const result =JSON.stringify(
{states:states, byCounty:byCounty},
(key, value) => (typeof value === 'bigint' ? parseInt(value) : value) // return everything else unchanged
)
res.json(result);index.js
<div className={styles.table_container}>
<h2>Teste</h2>
<DropDownMenu states={myData?myData.states:[]} byCounty={myData?myData.byCounty:[]}></DropDownMenu>
</div>我所拥有的:

发布于 2022-04-29 20:34:25
下面是一个自包含的示例,演示如何从模拟API (异步函数)中“获取”选项,并使用结果呈现一个顶级选项列表,使用所选选项对依赖的选项列表执行相同的操作。代码是注释的,如果有什么不清楚的地方,我可以进一步解释。
为了简单起见,示例不使用州和县,但依赖关系是相同的。
body { font-family: sans-serif; }
.select-container { display: flex; gap: 1rem; }
select { font-size: 1rem; padding: 0.25rem; }<div id="root"></div><script src="https://unpkg.com/react@18.1.0/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@18.1.0/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.17.10/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">
// import * as ReactDOM from 'react-dom/client';
// import {
// type Dispatch,
// type ReactElement,
// type SetStateAction,
// useEffect,
// useRef,
// useState,
// } from 'react';
// This Stack Overflow snippet demo uses UMD modules instead of the above import statments
const {
useEffect,
useRef,
useState,
} = React;
// The next section is just a mock API for getting dependent options (like your States/Counties example):
async function getOptionsApi (level: 1): Promise<string[]>;
async function getOptionsApi (
level: 2,
level1Option: string,
): Promise<string[]>;
async function getOptionsApi (
level: 1 | 2,
level1Option?: string,
) {
const OPTIONS: Record<string, string[]> = {
colors: ['red', 'green', 'blue'],
numbers: ['one', 'two', 'three'],
sizes: ['small', 'medium', 'large'],
};
if (level === 1) return Object.keys(OPTIONS);
else if (level1Option) {
const values = OPTIONS[level1Option];
if (!values) throw new Error('Invalid level 1 option');
return values;
}
throw new Error('Invalid level 1 option');
}
// This section includes the React components:
type SelectInputProps = {
options: string[];
selectedOption: string;
setSelectedOption: Dispatch<SetStateAction<string>>;
};
function SelectInput (props: SelectInputProps): ReactElement {
return (
<select
onChange={(ev) => props.setSelectedOption(ev.target.value)}
value={props.selectedOption}
>
{props.options.map((value, index) => (
<option key={`${index}.${value}`} {...{value}}>{value}</option>
))}
</select>
);
}
function App (): ReactElement {
// Use a ref to track whether or not it's the initial render
const isFirstRenderRef = useRef(true);
// State for storing the top level array of options
const [optionsLvl1, setOptionsLvl1] = useState<string[]>([]);
const [selectedLvl1, setSelectedLvl1] = useState('');
// State for storing the options that depend on the selected value from the level 1 options
const [optionsLvl2, setOptionsLvl2] = useState<string[]>([]);
const [selectedLvl2, setSelectedLvl2] = useState('');
// On the first render only, get the top level options from the "API"
// and set the selected value to the first one in the list
useEffect(() => {
const setOptions = async () => {
const opts = await getOptionsApi(1);
setOptionsLvl1(opts);
setSelectedLvl1(opts[0]!);
};
if (isFirstRenderRef.current) {
isFirstRenderRef.current = false;
setOptions();
}
}, []);
// (Except for the initial render) every time the top level option changes,
// get the dependent options from the "API" and set
// the selected dependent value to the first one in the list
useEffect(() => {
const setOptions = async () => {
const opts = await getOptionsApi(2, selectedLvl1);
setOptionsLvl2(opts);
setSelectedLvl2(opts[0]!);
};
if (isFirstRenderRef.current) return;
setOptions();
}, [selectedLvl1]);
return (
<div>
<h1>Dependent select options</h1>
<div className="select-container">
<SelectInput
options={optionsLvl1}
selectedOption={selectedLvl1}
setSelectedOption={setSelectedLvl1}
/>
<SelectInput
options={optionsLvl2}
selectedOption={selectedLvl2}
setSelectedOption={setSelectedLvl2}
/>
</div>
</div>
);
}
const reactRoot = ReactDOM.createRoot(document.getElementById('root')!)
reactRoot.render(<App />);
</script>
发布于 2022-04-29 21:15:34
您可以使用自定义钩子来完成此操作。
关键是,在您的代码中,第二个下拉列表应该在第一个下拉列表的日期观察更改&对这些更改做出反应。在React中,您可以使用useEffect() (大多数情况下)来完成此操作:
useEffect(() => {
reactingToChanges()
}, [watchedVariable])在片段里,
// THE IMPORTANT PART IS IN A COMMENT TOWARDS THE BOTTOM
const { useEffect, useState } = React;
const useFetchStates = () => {
const [states, setStates] = useState([]);
const fetchStates = () => {
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
const urlencoded = new URLSearchParams();
urlencoded.append("iso2", "US");
const requestOptions = {
method: "POST",
headers: myHeaders,
body: urlencoded,
redirect: "follow"
};
fetch(
"https://countriesnow.space/api/v0.1/countries/states",
requestOptions
)
.then((response) => response.json())
.then(({ data: { states } }) => setStates(states))
.catch((error) => console.log("error", error));
};
if (!states.length) {
fetchStates();
}
return {
states
};
};
const useFetchCounties = () => {
const [countiesByState, setCountiesByState] = useState({});
const [counties, setCounties] = useState([]);
const fetchCounties = (state) => {
if (state in countiesByState) {
setCounties(countiesByState[state]);
} else if (state) {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((response) => response.json())
.then((json) => {
const mappedCounties = json.map(({ id, title }) => ({
id: `${state}-${id}`,
title: `${state} - ${title}`
}));
setCounties(mappedCounties);
setCountiesByState((prevState) => ({
...prevState,
[state]: mappedCounties
}));
});
} else {
setCounties([]);
}
};
return {
counties,
fetchCounties
};
};
const Selector = ({ options = [], onChange, dataType }) => {
return (
<select onChange={(e) => onChange(e.target.value)} defaultValue={"DEFAULT"}>
<option disabled value="DEFAULT">
SELECT {dataType}
</option>
{options.map(({ name, val }) => (
<option key={val} value={val}>
{name}
</option>
))}
</select>
);
};
const App = () => {
const { states = [] } = useFetchStates();
const [selectedState, setSelectedState] = useState("");
const { counties, fetchCounties } = useFetchCounties();
const [selectedCounty, setSelectedCounty] = useState("");
// here's the heart of this process, the useEffect():
// when the selectedState variable changes, the
// component fetches the counties (based on currently
// selected state) and resets the currently selected
// county (as we do not know that at this time)
useEffect(() => {
fetchCounties(selectedState);
setSelectedCounty("");
}, [selectedState]);
const handleSelectState = (val) => setSelectedState(val);
const handleSelectCounty = (val) => setSelectedCounty(val);
return (
<div>
<Selector
options={states.map(({ name, state_code }) => ({
name,
val: state_code
}))}
onChange={handleSelectState}
dataType={"STATE"}
/>
<br />
<Selector
options={counties.map(({ id, title }) => ({
name: title,
val: id
}))}
onChange={handleSelectCounty}
dataType={"COUNTY"}
/>
<br />
Selected state: {selectedState}
<br />
Selected county: {selectedCounty}
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id="root"></div>
发布于 2022-05-01 16:23:23
你问这个问题的方式导致了对你的问题的不同解释,@muka.gergely和@jsejcksn的答案都是非常好的解决方案,但这更符合你真正想要的。因为你只想从选定的州得到值并从后端获取县,你可以这样做:
functions.js
// change to a function that gets a state as parameter
const byCounty = async (selectedState) => {
return await prisma.county.groupBy({
by:["county"],
where: {
date: dateTime,
// use the received parameter here to fetch the counties
state: selectedState
},
_sum:{
cases:true,
},
})
};menu.js
export default function DropDownMenu(props){
if(!props.states) return
return(
<table>
<body>
<select
// use the byCounty function with the selected value to fetch the counties
onChange={ async (e) => {
await byCounty(e.target.value)
}}
>
{props.states.map(states=>
<option>{states.state}</option>
)}
</select>
<select >
{props.byCounty.map(byCounty=>
<option>{byCounty.county}</option>
)}
</select>
</body>
</table>
)
}仅此而已,如果你想让这个选项--县和州--一起工作,你也可以在其他答案的背后使用这个想法。希望我帮了你!
https://stackoverflow.com/questions/72061931
复制相似问题