簡體   English   中英

一個下拉菜單會影響另一個下拉菜單

[英]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 調用。

您將有三個選項可以在兩個單獨的組件之間建立連接。

  1. 使父母成為兩個孩子之間的連接器。
 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.
  1. 您可以使用全局 state 樹、state 管理庫(如 Redux、MobX 或 Flux)來幫助您管理單一數據源。 因此,當您在一個組件中調度操作時,可以在另一個組件中檢測到 state,然后使用 useEffect 掛鈎再次觸發,使用 state 作為依賴項。

  2. 另一種模式是使用上下文 API,但即使對我來說,雖然了解這些概念,但我很少使用它。

您可以在此處找到更多解釋和示例。

https://reactjs.org/docs/context.html#updating-context-from-a-nested-component

React.js - 兄弟組件之間的通信

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM