Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
143 views
in Technique[技术] by (71.8m points)

reactjs - React: Custom Component in double map loop don't render

i am struggling to a problem in React. I am working on a modal Form using the Material-UI Field. Each Field type like Select, Text and Shrink have their own Component. To handle more complex event like display more field depending on a field's value, i create a new component FormField with a main Field and all the other field that will be display.

I declare the component like this:

<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;
    }
}

Here I use the Hook [nodeField] in the return to check if there is the value of the main Field respond to one of the condition in an props arrayConditionDisplayChild. I work with a another Hook [arrayChildField] witch is an array of an array of object and each element of the first array represent all the information for the child field to display. If one of the condition is true then a new loop map is starting creating new Component Field with a key.

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>
    );

I don't get it why the main Component field render correctly but the nested Field don't. Note that i have tried to replace the nested Field component by a regular h1 or p element with a key and it actually work.

So i guess that might be a problem about rendering Custom Component in a double loop. What did i do wrong? Thanks in advance.

question from:https://stackoverflow.com/questions/65936498/react-custom-component-in-double-map-loop-dont-render

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you using Curly Braces, yon need to use return () like this:

{
                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>)
                    })
                ))
            } 

other wise you can use like that:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...