'Can't display data in inputfields

I'm seeking to display the current-state from the database in input fields so that the user sees what is in there and can change whatever he wants.

I have three arrays: lis, videos, and themes. lis and themes are displayed. Because I have three objects in my videos array, I want to map through it. Directly after looping, I do console.log my parameter and get the right entries, but they are not displayed. And I am getting the error:

Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.

Here is the code:

  const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
    const [data, setData] = useState({
        lis: [""],
        videos:[
                {
                    iframe:"",
                    ressort:"",
                    theme:"",
                    title:"",
                },
                {
                    iframe:"",
                    ressort:"",
                    theme:"",
                    title:"",
                },
                {
                    iframe:"",
                    ressort:"",
                    theme:"",
                    title:"",
                }, 
        ],
        themen:[""],
    })
    
    const {lis, videos, themen} = data;
    useEffect(()=>{
        if(isError){
            window.alert(message);
        }
        if(id){
            dispatch(getDropdownRessort(id));
        }
            return ()=>{
                dispatch(reset());
            }
        
    }, [dispatch, isError, message, id]);
    
    useEffect(()=>{
        
            if(dropdownRessort){
                setData({...dropdownRessort})
            }
            return dispatch(reset());
    },[dropdownRessort, dispatch]);
    
    const updateData = (e)=>{
        const {value} = e.target 
        setData((prevState)=>({
            ...prevState,
            [e.target.getAttribute("name")]: value,
          }))
    }
    const onSubmit = (e)=>{
        e.preventDefault();
        const updateDropdownRessortData = {
            lis,
            videos,
            themen,
        }
        dispatch(updateDropdownRessort(updateDropdownRessortData));
}

In the return:

<VideoWrapper>
                    <DataHolder>
                        {data.videos?.map((video, index)=>(
                            <div key={index}>
                                 <VideoSection>
                                     {console.log(video)}
                                    <FormGroup>
                                        <Label htmlFor={`ressortvideo_ + ${index} + _iframe`}>{`Video ${index}`}</Label>
                                        <Input type="text" name={`ressortvideo_ + ${index} + _iframe`} id={`ressortvideo_ + ${index} + _iframe`}
                                         value={video.iframe}  onChange={updateData}/>
                                    </FormGroup>
                                    <FormGroup>
                                        <Label htmlFor={`ressortvideo_ + ${index} + _ressort`}>{`Video ${index} Ressortzuordnung`}</Label>
                                        <Input type="text" name={`ressortvideo_ + ${index} + _ressort`} id={`ressortvideo_ + ${index} + _ressort`} value={video.ressort} onChange={updateData}/>
                                    </FormGroup>
                                    <FormGroup>
                                        <Label htmlFor={`ressortvideo_ + ${index} + _theme`}>{`Video ${index} Themenzuordnung`}</Label>
                                        <Input type="text" name={`ressortvideo_ + ${index} + _theme`} id={`ressortvideo_ + ${index} + _theme`}  value={video.theme} onChange={updateData}/>
                                    </FormGroup>
                                    <FormGroup>
                                        <Label htmlFor={`ressortvideo_ + ${index} + _title`}>{`Video ${index} Titelzuordnung`}</Label>
                                        <Input type="text" name={`ressortvideo_ + ${index} + _title`} id={`ressortvideo_ + ${index} + _title`}  value={video.title} onChange={updateData}/>
                                    </FormGroup>
                                </VideoSection>
                            </div>
                        ))}
                        </DataHolder>
                </VideoWrapper>


Solution 1:[1]

The issue is happening because the input fields and the state are not attached together properly. Just to give you an instance, the name of any input in your list would be 'ressortvideo_1_ressort'.

And on updateData, you are trying to add new property which is 'ressortvideo_1_ressort' which is not existing previously and hence the binding is not proper.

I would suggest try something like this.

Set the name property as follows:

name={`iframe_${index}`}

This will be similar to other properties as well like theme, title, etc.

In the updateData

const target = e.target.name.split("_");
const index = target[1];
const name = target[0];
const tempData = data;
tempData.videos[index] = {...tempData.videos[index], [name]: e.target.value};
setData({...tempData});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tirth Trivedi