【问题标题】:React: Custom Component in double map loop don't render反应:双地图循环中的自定义组件不呈现
【发布时间】:2021-01-28 11:46:09
【问题描述】:

我正在努力解决 React 中的一个问题。 我正在使用 Material-UI 字段处理模态表单。 Select、Text 和 Shrink 等每种 Field 类型都有自己的 Component。 为了处理更复杂的事件,例如根据字段的值显示更多字段,我创建了一个新组件 FormField,其中包含一个主字段和将显示的所有其他字段。

我这样声明组件:

<FormField 
         nodeField={values[4]} 
         required={values[4].required} 
         childField={[values.slice(5,7),values.slice(7,values.length)]} 
         arrayConditionDisplayChild={[(element)=>element.value == "Factor and Offset",(element)=>element.value == "2 points calibration"]}
/>
import React, { useState, useEffect } from 'react';

import Field from './Field.jsx';

export default function FormField(props)
{
    const [arrayCurrentIndex, setArrayCurrentIndex] = useState(0);
    const [arrayChildField, setArrayChildField] = useState(props.childField); // Hook comportant un tableau de tableau d'objet contenant chacun les informations de l'ensemble des champs enfants
    const [nodeField, setNodeField] = useState(props.nodeField);

    const [isComplete, setIsComplete] = useState(false);

    console.log("form field");

    const handleFieldChange = (fieldId, valueChange) => {
        console.log("handleFieldChange")
        if (nodeField.id == fieldId)
        {
            console.log(valueChange);
            let newNodeObject = Object.assign({},nodeField);
            newNodeObject.value = valueChange;
            console.log(newNodeObject);
            setNodeField(newNodeObject);
        }
        else
        {
            for (let i = 0; i < arrayChildField.length ; i++)
            {
                let j = arrayChildField[i].findIndex((element)=>element.id == fieldId);
                if (j != -1)
                {
                    //JSON.parse(JSON.stringify(nodeField)
                    let newChildArray = arrayChildField[i][j].slice(0);
                    newChildArray[i][j].value = valueChange;
                    setArrayChildField(newChildArray);
                }
            }
        }
    }

    useEffect(()=>{

    },[JSON.stringify(nodeField),JSON.stringify(arrayChildField)])

    return(
        <div>
            <Field objectField={props.nodeField} isRequired={props.required} handleFieldChange={handleFieldChange}/>
            {
                arrayChildField.map((childField, index) => (
                    props.arrayConditionDisplayChild[index](nodeField) && 
                    childField.map((field) => {
                        <div key={field.id}>
                            <Field objectField={field} isRequired={props.required} handleFieldChange={handleFieldChange}/>
                        </div>
                    })
                ))
            }
        </div>
    );
}
import React, { useState, useEffect } from 'react';

import FormText from './FormText.jsx';
import FormShrink from './FormShrink.jsx';
import FormSelect from './FormSelect.jsx';

export default function Field(props)
{
    console.log(props);
    switch(props.objectField.type)
    {
        case "Text":
            console.log("text");
            return (
                <FormText id={props.objectField.id} label={props.objectField.label} required={props.isRequired} onChange={props.handleFieldChange}/>
            );
            break;
        case "Shrink":
            console.log("Shrink");
            return (
                <FormShrink key={props.objectField.id} id={props.objectField.id} label={props.objectField.label} required={props.isRequired} condition={props.objectField.condition} onChange={props.handleFieldChange}/>
            );
            break;
        case "Select":
            console.log("Select");
            return (
                <FormSelect id={props.objectField.id} label={props.objectField.label} required={props.isRequired} currency={props.objectField.currency} onChange={props.handleFieldChange}/>
            );
            break;
    }
}

这里我在return中使用Hook [nodeField] 来检查是否有主Field的值响应一个props中的条件之一arrayConditionDisplayChild。 我使用另一个 Hook [arrayChildField] 女巫是一个对象数组的数组,第一个数组的每个元素代表要显示的子字段的所有信息。 如果其中一个条件为真,则新的循环映射开始使用键创建新组件 Field

return(
        <div>
            <Field objectField={props.nodeField} isRequired={props.required} handleFieldChange={handleFieldChange}/>
            {
                arrayChildField.map((childField, index) => (
                    props.arrayConditionDisplayChild[index](nodeField) && 
                    childField.map((field) => {
                        <div key={field.id}>
                            <Field objectField={field} isRequired={props.required} handleFieldChange={handleFieldChange}/>
                        </div>
                    })
                ))
            }
        </div>
    );

我不明白为什么主组件字段正确呈现但嵌套字段不正确。 请注意,我已尝试将嵌套的 Field 组件替换为带有键的常规 h1 或 p 元素,它确实有效。

所以我想这可能是在双循环中呈现自定义组件的问题。 我做错什么了? 提前致谢。

【问题讨论】:

    标签: reactjs react-hooks material-ui


    【解决方案1】:

    如果你使用花括号,你需要像这样使用 return ():

    {
                    arrayChildField.map((childField, index) => (
                        props.arrayConditionDisplayChild[index](nodeField) && 
                        childField.map((field) => {
        return
                          (  <div key={field.id}>
                                <Field objectField={field} isRequired={props.required} handleFieldChange={handleFieldChange}/>
                            </div>)
                        })
                    ))
                } 
    

    否则你可以这样使用:

    {
                    arrayChildField.map((childField, index) => (
                        props.arrayConditionDisplayChild[index](nodeField) && 
                        childField.map((field) => (
                            <div key={field.id}>
                                <Field objectField={field} isRequired={props.required} handleFieldChange={handleFieldChange}/>
                            </div>
                        ))
                    ))
                }
    

    【讨论】:

    • 感谢您的回复,遗憾的是我已经尝试过这两种语法,但它们都不适合我
    • 您是否检查过您的第二张地图是否正常工作?
    • 是的,我确实检查了我的第二张地图,它甚至进入了 Field 组件并进入了切换条件,但它只是卡在它上面
    【解决方案2】:

    好吧,我觉得真的很蠢,我从来没有检查过我的组件 FormShrink,他的条件渲染是

    return (
          active && <TextField className="textfield" error={errorFormShrink} id={props.id} label={props.required ? props.label + " *" : props.label} type="number" InputLabelProps={{shrink: true,}} variant="filled" helperText={helperText} onChange={handleChange}/>
        );
    

    witch active 一开始是假的。 谢谢你 Waleed Nassir 仍然帮助我。

    【讨论】:

      猜你喜欢
      • 2023-02-01
      • 2023-02-09
      • 2023-02-14
      • 2018-07-28
      • 2020-12-11
      • 1970-01-01
      • 2018-03-26
      • 2017-05-12
      • 2020-09-02
      相关资源
      最近更新 更多