簡體   English   中英

嵌套對象值的 JSX 條件渲染

[英]JSX Conditional Rendering for Nested Object Values

我試圖讓“抽認卡”在未回答時不顯示背景顏色,正確回答時顯示綠色,錯誤回答時顯示黃色。 每張卡片的屬性都存儲在一個嵌套對象中。 我在使用條件渲染來正確顯示我的內容時遇到問題。

代碼:這里是我想要完成的,但是JSX條件語句只是在className中注冊了最后一個語句。

<div className="row">
    {Object.keys(this.state.selections).map( (lang, index) => (
        <>
            {Object.keys(this.state.selections[lang]).map( (cat, index) => (
                <>
                {Object.keys(this.state.selections[lang][cat]).map( (sect, index)=> (
                    <>
                    {Object.keys(this.state.selections[lang][cat][sect]).map( (letter, index)=> (
                        <>
                        {this.state.selections[lang][cat][sect][letter].show &&
                            <div className={
                                (this.state.selections[lang][cat][sect][letter].correct ? correct: unanswered),
                                (this.state.selections[lang][cat][sect][letter].incorrect ? incorrect : unanswered)
                            } key= {index}>
                            </div>
                        }
                        </>
                    ))}
                    </>
                ))}
                </>
            ))}
        </>
    ))}
</div>

本質上,我想在 className 中放置一個條件語句,以根據對象屬性值為 true/false 來更改背景。

對象模型:

{
    "Hiragana": {
        "Main Kana": {
            "Vowels": {
                "a": {
                    "characterName":  "A",
                    "character":  "あ",
                    "unicode":  "\u0026‌#12354;",
                    "hexEncoding":  "\u0026‌#x3042",
                    "englishTranslation":  "a",
                    "alternateEnglishTranslation":  "",
                    "isLetter":  "1",
                    "alphabet":  "hir",
                    "show": false,
                    "answer": "",
                    "correct": false,
                    "incorrect": false,
                    "unanswered": true
                    },

額外問題:必須遍歷每個對象層似乎有點混亂和乏味......有什么好方法可以縮短它嗎? langcat是通過輸入選擇的,因此它們不能被硬編碼。 雖然我目前的解決方案“有效”,但我想盡可能提高自己。

更新: @CertainPerformance 提供的解決方案中的工作代碼

<div className="row">
    {Object.keys(this.state.selections).map(lang => 
        Object.values(this.state.selections).map( (cat) =>
            Object.values(cat).map((sect, indexCat) =>
                Object.values(sect).map((sectLetters, indexSect) =>
                    Object.values(sectLetters).map((letter, indexSectL) =>
                        letter.show &&
                        <div
                            className={getBgClass(letter)}
                            key={indexSectL}>
                            <div>
                                <h5 className="card-title" >{letter.character}</h5>
                                <input data-lang={lang} data-cat={Object.getOwnPropertyNames(cat)[indexCat]} data-sect={Object.getOwnPropertyNames(sect)[indexSect]} type="text" name={letter.characterName} value={letter.answer} onChange={this.handleChange.bind(this)} />
                            </div>
                        </div>
                    )
                )
            )
        )
    )}
</div>

對於那些對我訪問 Object.values 生成的數組的解釋感到困惑的人,這里有一個帶有簡單 console.log 的示例以更好地解釋。

Object.values(this.state.selections).map((cat) =>{
    Object.values(cat).map((sect, indexCat) => {
        console.log("Cat: ", Object.getOwnPropertyNames(cat)[indexCat]);
    });
});

我不確定您當前的代碼是否像您期望的那樣工作。 這里:

className={
  (this.state.selections[lang][cat][sect][letter].correct ? correct : unanswered),
  (this.state.selections[lang][cat][sect][letter].incorrect ? incorrect : unanswered)
}

您正在調用逗號運算符,它僅計算逗號分隔列表中的最終表達式。 它相當於:

className={
  (this.state.selections[lang][cat][sect][letter].incorrect ? incorrect : unanswered)
}

要修復它,請使用嵌套條件運算符,或將其傳遞給函數。

為了使您的代碼更簡潔,而不是迭代對象的,而是迭代對象的 返回數組時也不需要片段<></>

<div className="row">
    {Object.values(this.state.selections).map(selection =>
        Object.values(selection).map(cat =>
            Object.values(cat).map(sect =>
                Object.values(sect).map((letter, index) =>
                    letter.show &&
                    <div
                        className={
                            letter.correct
                                ? correct
                                : letter.incorrect
                                    ? incorrect
                                    :
                                    unanswered
                        }
                        key={index}
                    >
                    </div>
                )
            )
        )
    )}
</div>

為了避免嵌套條件,如果這是您的偏好,請執行以下操作:

<div
    className={getClass(letter)}
    key={index}
></div>
const getClass = (letter) => {
  if (letter.correct) return correct;
  if (letter.incorrect) return incorrect;
  return unanswered;
};

您還可以考慮更改您的模型,以便問題狀態(正確/不正確/未回答)是單個屬性,而不是多個屬性,例如,而不是

"correct": false,
"incorrect": false,
"unanswered": true

answerState: 2

其中 2 對應於未回答,1 對應於不正確,0 對應於正確 - 或類似的東西。 然后你可以使用一個數組來查找合適的類名:

className={classNames[letter.answerState]}
const classNames = [correct, incorrect, unanswered];

暫無
暫無

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

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