简体   繁体   中英

React - A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined

I am building my first own Mern-Stack. I have a dropdownmenue with three contents, menuepoints(lis), videos and themes. Currently I am writing an edit-component for this dropdown, and I am getting the error, which is the title of my post. It is clear, the users should get the current state displayed, but only menuepoints and themes are displayed, and when I try to update them, console say the same and the value is undefined. I tried something with defaultValue, I tried to define the value before setData, but nothing changes. Can someone help me out? Thanks for your help.

Here is my code:

const DropdownRessortEdit = () => {
    const dispatch = useDispatch();
    const { id } = useParams();
    const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
   console.log({...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]);
    
  console.log(data);
    const updateData = (e)=>{
        const {value} = e.target //changes nothing
        setData((prevState)=>({
            ...prevState,
            [e.target.name]: value,
          }))
    }
    const onSubmit = (e)=>{
        e.preventDefault();
        const updateDropdownRessortData = {
            lis,
            videos,
            themen,
        }
        dispatch(updateDropdownRessort(updateDropdownRessortData));
    }
    if(isLoading){
        return <Spinner/>
    }
  return (
   
    <Container>
        <Navbar/>
        <TitleHolder>
            <Title>Update DropdownRessort</Title>
        </TitleHolder>
        <ContentHolder>
            {data ? 
            <UpdateForm onSubmit={onSubmit} encType="multipart/form-data">
            <section className="menupoints">
                  <Label htmlFor="lis_ressorts">Menüpunkte Ressorts</Label>
                  <Input type="text" name="lis_ressorts" id="lis_ressorts" value={data.lis} onChange={updateData}/>
                </section>
                <VideoWrapper>
                    <DataHolder>
                        {data.videos?.map((video, index)=>(
                            <div key={index}>
                                 <VideoSection>
                                    <FormGroup>
                                        <Label htmlFor={`ressortvideo_ + ${index} + _iframe`}>{`Video ${index}`}</Label>
                                        <Input type="url" name={`ressortvideo_ + ${index} + _iframe`} id={`ressortvideo_ + ${index} + _iframe`}
                                        defaultValue={""} 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>
                <section className="themen">
                  <Label htmlFor="themen_ressorts">Themen</Label>
                  <Input type="text" name="themen_ressorts" id="themen_ressorts" value={data.themen} onChange={updateData}/>
                </section>
                        <ButtonHolder>
                            <UpdateButton type="submit">Update</UpdateButton>
                        </ButtonHolder> 
 
            </UpdateForm>
            : null}
        </ContentHolder>
        <Footer/>
    </Container>
  )
}

export default DropdownRessortEdit

Name is an attribute, use getAttribute("name") instead of e.target.name

const DropdownRessortEdit = () => {
    const dispatch = useDispatch();
    const { id } = useParams();
    const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
   console.log({...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]);
    
  console.log(data);
    const updateData = (e)=>{
        const {value} = e.target //changes nothing
        setData((prevState)=>({
            ...prevState,
            [e.target.getAttribute('name')]: value,
          }))
    }
    const onSubmit = (e)=>{
        e.preventDefault();
        const updateDropdownRessortData = {
            lis,
            videos,
            themen,
        }
        dispatch(updateDropdownRessort(updateDropdownRessortData));
    }
    if(isLoading){
        return <Spinner/>
    }
  return (
   
    <Container>
        <Navbar/>
        <TitleHolder>
            <Title>Update DropdownRessort</Title>
        </TitleHolder>
        <ContentHolder>
            {data ? 
            <UpdateForm onSubmit={onSubmit} encType="multipart/form-data">
            <section className="menupoints">
                  <Label htmlFor="lis_ressorts">Menüpunkte Ressorts</Label>
                  <Input type="text" name="lis_ressorts" id="lis_ressorts" value={data.lis} onChange={updateData}/>
                </section>
                <VideoWrapper>
                    <DataHolder>
                        {data.videos?.map((video, index)=>(
                            <div key={index}>
                                 <VideoSection>
                                    <FormGroup>
                                        <Label htmlFor={`ressortvideo_ + ${index} + _iframe`}>{`Video ${index}`}</Label>
                                        <Input type="url" name={`ressortvideo_ + ${index} + _iframe`} id={`ressortvideo_ + ${index} + _iframe`}
                                        defaultValue={""} 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>
                <section className="themen">
                  <Label htmlFor="themen_ressorts">Themen</Label>
                  <Input type="text" name="themen_ressorts" id="themen_ressorts" value={data.themen} onChange={updateData}/>
                </section>
                        <ButtonHolder>
                            <UpdateButton type="submit">Update</UpdateButton>
                        </ButtonHolder> 
 
            </UpdateForm>
            : null}
        </ContentHolder>
        <Footer/>
    </Container>
  )
}

export default DropdownRessortEdit

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM