点击国旗图标切换网站语言的代码优化及实现疑问
React国旗语言切换实现与代码优化方案
1. 优化基于i18n的重复代码
你当前代码里每个语言都写了单独的处理函数,重复度极高。可以把语言配置抽成数组,用循环渲染国旗按钮,只保留一个通用的语言切换函数,大幅减少冗余代码:
首先定义语言配置数组,把每个语言的国旗代码、语言代码、唯一ID整合到一起:
const languages = [ { countryCode: "BR", langCode: "pt", id: "flag__br" }, { countryCode: "US", langCode: "en", id: "flag__en" }, { countryCode: "FR", langCode: "fr", id: "flag__fr" }, { countryCode: "ES", langCode: "es", id: "flag__es" }, ];
然后替换原来的多个处理函数为一个通用函数:
const handleLanguageChange = (langCode) => { i18n.changeLanguage(langCode); };
最后用循环渲染所有国旗按钮,不用重复写标签:
<div className="page__idiom"> {languages.map((lang) => ( <a key={lang.id} href="#" onClick={(e) => { e.preventDefault(); // 阻止a标签默认跳转行为 handleLanguageChange(lang.langCode); }} id={lang.id} > <ReactCountryFlag className="flag__attributes" countryCode={lang.countryCode} svg /> </a> ))} </div>
以后新增或修改语言,只需要调整languages数组即可,不用再写重复的函数和标签,代码维护性大幅提升。
2. 区分标签的各个ID
上面的优化方案已经通过配置数组的id字段,为每个标签生成了唯一ID(比如flag__br、flag__en)。如果不需要预先定义ID,也可以直接在循环时根据语言标识动态拼接,比如id={flag__${lang.langCode}},同样能保证每个标签ID唯一,方便后续做样式调整或DOM操作时区分。
3. 使用React State管理语言状态
i18n本身已经维护了全局语言状态,但如果想通过React的state来管理组件内的语言状态,同步实现切换效果,可以这样做:
首先引入useState和useEffect钩子:
import { useState, useEffect } from 'react';
然后在组件内定义state,并同步i18n的语言变化:
const [currentLang, setCurrentLang] = useState(i18n.language); // 监听i18n的语言变化事件,同步更新组件state useEffect(() => { const handleLangChange = () => { setCurrentLang(i18n.language); }; i18n.on('languageChanged', handleLangChange); // 组件卸载时移除监听,避免内存泄漏 return () => { i18n.off('languageChanged', handleLangChange); }; }, []); // 修改语言切换函数,同时更新state和i18n的全局状态 const handleLanguageChange = (langCode) => { setCurrentLang(langCode); i18n.changeLanguage(langCode); };
有了currentLang状态后,还可以实现当前选中国旗的高亮效果,比如给选中的标签加个激活类:
<a key={lang.id} href="#" onClick={(e) => { e.preventDefault(); handleLanguageChange(lang.langCode); }} id={lang.id} className={currentLang === lang.langCode ? 'active-flag' : ''} > <ReactCountryFlag className="flag__attributes" countryCode={lang.countryCode} svg /> </a>
之后只要给.active-flag写对应的CSS样式,就能直观显示当前选中的语言。
完整优化后的代码
import { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import ReactCountryFlag from 'react-country-flag'; import CTA from './CTA'; import HeaderSocials from './HeaderSocials'; const Header = () => { const { t } = useTranslation(); const [currentLang, setCurrentLang] = useState(i18n.language); const languages = [ { countryCode: "BR", langCode: "pt", id: "flag__br" }, { countryCode: "US", langCode: "en", id: "flag__en" }, { countryCode: "FR", langCode: "fr", id: "flag__fr" }, { countryCode: "ES", langCode: "es", id: "flag__es" }, ]; useEffect(() => { const handleLangChange = () => { setCurrentLang(i18n.language); }; i18n.on('languageChanged', handleLangChange); return () => { i18n.off('languageChanged', handleLangChange); }; }, []); const handleLanguageChange = (langCode) => { setCurrentLang(langCode); i18n.changeLanguage(langCode); }; return( <header> <div className="header__bg"> </div> <div className="container header__container"> <h5>{t("greetings")}</h5> <h1>{t("name")}</h1> <h5 className="text-light">{t("course")}</h5> <CTA /> <HeaderSocials /> <div className="page__idiom"> {languages.map((lang) => ( <a key={lang.id} href="#" onClick={(e) => { e.preventDefault(); handleLanguageChange(lang.langCode); }} id={lang.id} className={currentLang === lang.langCode ? 'active-flag' : ''} > <ReactCountryFlag className="flag__attributes" countryCode={lang.countryCode} svg /> </a> ))} </div> </div> <div className="language__dropdown"> <img src="" alt="" /> </div> </header> ) } export default Header;
内容的提问来源于stack exchange,提问作者Caio
相关产品推荐
相关产品推荐

