Search code examples
javascriptreactjsonchangereact-modal

react-modal - onChange on input is not updating state


I hope you will be able to help me with an answer to my question. I am using react-modal and inside the modal I have an input where users can write an email. When writing the email it should update the state but that is not happening.

What is happening right now is that the model re-renders every time I write a new letter and that results in the state only updating with the first letter I typed and then focus is lost.

I am using react hooks. I know that changes a bit.

My code looks like the following:

    import React, { useState, useContext } from 'react';
import AppContext from '../../AppContext.jsx';
import GroupContext from './GroupContext.jsx';
import Section from '../../Elements/PageContent/Section.jsx';
import PageTitle from '../../Elements/PageContent/PageTitle.jsx';
import WhiteContainer from '../../Elements/PageContent/WhiteContainer.jsx';
import { Form, FormGroup, FormSection, FormSection_Split, Label, Input, Select, Submit } from '../../Elements/Forms/FormCollection.jsx';
import { MusicGenres } from '../../Elements/Forms/MusicGenres.jsx';
import { Years } from '../../Elements/Forms/Years.jsx';
import { H3 } from '../../Elements/Fonts/FontCollection.jsx';
import { Icon } from '../../Elements/Image/ImageUtil.jsx';
import ReactModal from "react-modal";
import { useModal } from "react-modal-hook";

export default function Groups(props) {  
    const AC = useContext(AppContext);
    const GC = useContext(GroupContext);
    const [groupName, setGroupName] = useState("");
    const [groupDescription, setGroupDescription] = useState("");
    const [memberEmail, setMemberEmail] = useState("");
    const [groupMembers, setGroupMembers] = useState([]);
    const [showModal, hideModal] = useModal(() => (
        <ReactModal className="DialogPopup" isOpen ariaHideApp={false}>
            <Form>
                <FormGroup>
                    <FormSection>
                        <Label htmlFor="memberEmail" title="Email of your group member:" />
                        <Input type="email" name="memberEmail" value={memberEmail} onChange={(e) => setMemberEmail(e.target.value)} placeholder="@" />
                    </FormSection>
                </FormGroup>
            </Form>
            <button onClick={(e) => hideModal()} className="Close" aria-label="Close popup"><Icon iconClass="fal fa-times" /></button>
        </ReactModal>
    ), []);

    async function addObjectToGroupMembersArray(e) {
        e.preventDefault();
        console.log("Adding member");
    }

    return (
        <React.Fragment>
            <PageTitle title="Add group" />
            <Section>
                <Form>
                    <FormGroup>
                        <FormSection>
                            <WhiteContainer>
                                <Label htmlFor="groupName" title="Group name:" />
                                <Input type="text" name="groupName" value={groupName} onChange={(e) => setGroupName(e.target.value)} maxLength="60" required />
                                <span className="CharactersLeft">Characters left: {60 - groupName.length}</span>
                            </WhiteContainer>
                        </FormSection>
                        <FormSection>
                            <WhiteContainer>
                                <Label htmlFor="groupDescription" title="Describe your group:" />
                                <textarea name="groupDescription" id="groupDescription" value={groupDescription} onChange={(e) => setGroupDescription(e.target.value)} maxLength="500"></textarea>
                                <span className="CharactersLeft">Characters left: {500 - groupDescription.length}</span>
                            </WhiteContainer>
                        </FormSection>
                        <FormSection>
                            <WhiteContainer>
                                <Label htmlFor="groupMembers" title="List the emails of your group members?" />
                                <a href="#" className="AddLink" aria-label="Add member" title="Click to add a member" onClick={(e) => { e.preventDefault(); showModal(); }}>
                                    <Icon iconClass="fal fa-plus" />
                                </a>
                            </WhiteContainer>
                        </FormSection>
                        <FormSection className="FormSection--Submit">
                            <Submit text="Create group" />
                        </FormSection>
                    </FormGroup>
                </Form>
            </Section>
        </React.Fragment>
    );
}

Does anyone of you know why the modal is updating every time I type, resulting in not being able to write anything in the input. Should i use "ref" and if I should, how would I do that?

The onChange method I am using is always working, just not inside react-modal.


Solution

  • I finally figured it out. It's because modal is working a little like the useEffect hook. If i add memberEmail to the bottom of the modal state, then it is working.

    const [memberEmail, setMemberEmail] = useState("");
        const [showModal, hideModal] = useModal(() => (
            <ReactModal className="DialogPopup" isOpen ariaHideApp={false}>
                <Form>
                    <FormGroup>
                        <FormSection>
                            <Label htmlFor="memberEmail" title="Email of your group member:" />
                            <Input type="email" name="memberEmail" value={memberEmail} onChange={(e) => setMemberEmail(e.target.value)} placeholder="@" />
                        </FormSection>
                    </FormGroup>
                </Form>
                <button onClick={(e) => hideModal()} className="Close" aria-label="Close popup"><Icon iconClass="fal fa-times" /></button>
            </ReactModal>
        ), [memberEmail]);