[英]One dropdown menu affects another dropdown menu
我和我的朋友正在開發一個使用 Lexicala API 的 React 翻譯應用程序。 我們有兩個選擇器組件:一個用於源語言,一個用於目標語言。 用戶首先將 select 源語言,然后根據他們的選擇,第二個下拉菜單將填充可用的目標語言列表。 有人對我們如何使源語言選擇器組件中的 state 更新影響第二個組件有任何建議嗎?
我包含每個組件的代碼(不帶注釋)。 如果您認為我們已經做錯了什么,請告訴我。
SourceLanguageSelector.js
import React, {useState, useEffect} from 'react';
import { encode } from "base-64";
let headers = new Headers();
headers.append('Authorization', 'Basic ' + encode(process.env.REACT_APP_API_USERNAME + ":" + process.env.REACT_APP_API_PASSWORD));
const SourceLanguageSelector = () => {
const [loading, setLoading] = useState(true);
const [items, setItems] = useState([
{ label: "Loading...", value: "" }
]);
const [value, setValue] = useState();
useEffect(() => {
let unmounted = false;
async function getLanguages() {
const request = await fetch("https://dictapi.lexicala.com/languages", {
method: 'GET', headers: headers
});
const body = await request.json();
console.log(body);
const sourceLang = body.resources.global.source_languages;
const langName = body.language_names;
const compare = (sourceLanguage, languageName) => {
return sourceLanguage.reduce((obj, key) => {
if (key in languageName) {
obj[key] = languageName[key];
}
return obj;
}, {});
}
const sourceLanguageNames = compare(sourceLang, langName);
if (!unmounted) {
setItems(
Object.values(sourceLanguageNames).map((sourceLanguageName) => ({
label: sourceLanguageName,
value: sourceLanguageName
}))
);
setLoading(false);
}
}
getLanguages();
return () => {
unmounted = true;
}
}, []);
return (
<select
disabled={loading}
value={value}
onChange={e => setValue(e.currentTarget.value)}>
{items.map(item => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
);
};
export default SourceLanguageSelector;
TargetLanguageSelector.js
import React, { useState, useEffect } from 'react';
import { encode } from 'base-64';
let headers = new Headers();
headers.append('Authorization', 'Basic ' + encode(process.env.REACT_APP_API_USERNAME + ":" + process.env.REACT_APP_API_PASSWORD));
const TargetLanguageSelector = () => {
const [loading, setLoading] = useState(true);
const [items, setItems] = useState([
{ label: "Loading...", value: "" }
]);
const [value, setValue] = useState();
useEffect(() => {
let unmounted = false;
async function getLanguages() {
const request = await fetch("https://dictapi.lexicala.com/languages", {
method: 'GET', headers: headers
});
const body = await request.json();
console.log(body);
const targetLang = body.resources.global.target_languages;
const langName = body.language_names;
const compare = (targetLanguage, languageName) => {
return targetLanguage.reduce((obj, key) => {
if (key in languageName) {
obj[key] = languageName[key];
}
return obj;
}, {});
}
const targetLanguageNames = compare(targetLang, langName);
if (!unmounted) {
setItems(
Object.values(targetLanguageNames).map(target_languages =>
({
label: target_languages,
value: target_languages
}))
);
setLoading(false);
}
}
getLanguages();
return () => {
unmounted = true;
}
}, []);
return (
<select
disabled={loading}
value={value}
onChange={e => setValue(e.currentTarget.value)}>
{items.map(item => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
);
};
export default TargetLanguageSelector;
您可以通過父項在選擇之間協調 state。 將回調 function 傳遞給在 onChange 處理程序觸發時調用的Source
,將所選語言傳遞給父級。 在父級中,為當前選定的語言創建一塊 state 並將其作為道具傳遞給Target
。 在 target 中,您可以在依賴數組中使用帶有該道具的useEffect
,因此每當Source
中所選語言發生更改時, Target
都會進行適當的 api 調用。
您將有三個選項可以在兩個單獨的組件之間建立連接。
eg, Use a function props to trigger handler in parent. This handler will change the state of parent and it will lead to change the props of another children like how @EvanMorrison has answered.
您可以使用全局 state 樹、state 管理庫(如 Redux、MobX 或 Flux)來幫助您管理單一數據源。 因此,當您在一個組件中調度操作時,可以在另一個組件中檢測到 state,然后使用 useEffect 掛鈎再次觸發,使用 state 作為依賴項。
另一種模式是使用上下文 API,但即使對我來說,雖然了解這些概念,但我很少使用它。
您可以在此處找到更多解釋和示例。
https://reactjs.org/docs/context.html#updating-context-from-a-nested-component
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.