状态挂钩不会在 redux 存储更新

时间:2021-06-07 13:51:14

标签: reactjs redux react-redux react-hooks

我有并更新用户页面。存在基于功能组件的简单形式。我使用钩子来处理状态和输入参数。我从 redux 商店获得的默认参数(可以更改)(我在 useEffect 中获取它们)。页面加载存储更改后,bot hook 不会更新表单中的必要属性,并且存在空输入。我怎么能想到,在商店更新钩子之后会更新状态,但不会。我该如何解决这个问题?

组件:

const EditUserPage: React.FunctionComponent<Props> = () => {
    const dispatch = useDispatch();
    const history = useHistory();
    const {profileId} = useParams<UrlParams>();
    
    useEffect(() => {
        dispatch(getRolesList());
        console.log("URL PARAM=", profileId)
        dispatch(getProfileById(parseInt(profileId)));
    }, []);
    
    
    const isEmailDuplicated: boolean = useSelector(getEmailDuplicated);
    const rolesList: Array<PlainObject> = useSelector(userRolesList);
    const contetType: string = useSelector(adminContentType);
    const userProfileData: PlainObject = useSelector(selectedUserProfile);

    const [startDate, setStartDate] = useState<Date>(new Date());
    const [firstName, setFirstName] = useState<string>(userProfileData.firstName);
    const [lastName, setLastName] = useState<string>(userProfileData.lastName ? userProfileData.lastName : "");
    const [role, setRole] = useState<string>(userProfileData.user && userProfileData.user.roles[0].name);
    const [gender, setGender] = useState<string>(userProfileData.gender ? userProfileData.gender : "");
    const [address, setAddress] = useState<string>(userProfileData.address ? userProfileData.address : "");
    const [phone, setPhone] = useState<string>(userProfileData.telephone ? userProfileData.telephone : "");
    const [office, setOffice] = useState<string>(userProfileData.office ? userProfileData.office : "");
    const [socialNumber, setSocialNumber] = useState<string>(userProfileData.socialNumber ? userProfileData.socialNumber : "");
    const [about, setAbout] = useState<string>(userProfileData.about ? userProfileData.about : "");
    const [login, setLogin] = useState<string>(userProfileData.email ? userProfileData.email : "");

    const roleDropdownOptions = rolesList && rolesList.map((role) => {
        console.log("?????",userProfileData)
        return {
            key: role.id,
            text: role.name.toLowerCase(),
            value: role.name,
        }
    })

    //validate email
    const mailRegex = new RegExp(/^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/g);
    const isMailValid = login && mailRegex.test(login);

    //validate phone number
    const phoneRegex = new RegExp(/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s./0-9]*$/g)
    const isPhoneValid = phone && phoneRegex.test(phone);
    
    const handleSubmit = (event: { preventDefault: () => void; }) => {
        const dateFormat = require("dateformat");

        event.preventDefault();

        userProfileData["firstName"] = firstName;
        userProfileData["lastName"] = lastName;
        userProfileData["email"] = login;
        userProfileData["telephone"] = phone;
        userProfileData["about"] = about;
        userProfileData["office"] = office;
        userProfileData["address"] = address;
        userProfileData["socialNumber"] = socialNumber;
        userProfileData["dateOfBirth"] = dateFormat(startDate, "yyyy-mm-dd");
        userProfileData["gender"] = gender;

        const promise = new Promise(() => {
            return dispatch(updateProfile(userProfileData));
        })

        promise
            .then(() => history.push("/admin"))
            .then(() => {
                if (contetType === adminContentTypes.PERSONAL) {
                    dispatch(getPersonalProfiles());
                } else {
                    dispatch(getPatientProfiles());
                }
            })
    }

    return (
        <Fragment>
            <Header as="h1">
                EDIT USER
            </Header>
            <Divider/>
            <Form onSubmit={handleSubmit}>
                {
                    isEmailDuplicated &&
                    <Message
                        negative={true}
                        header="Account already exists"
                        content="An account already exists for this email address, please log in or confirm your email address is correct"
                    />
                }
                <Form.Group widths="equal">
                    <Form.Input
                        label="First name"
                        name="firstName"
                        value={firstName}
                        required={true}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFirstName(e.target.value)}
                    />
                    <Form.Input
                        label="Last name"
                        name="lastName"
                        value={lastName}
                        required={true}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setLastName(e.target.value)}
                    />
                    <Form.Input
                        label="Email"
                        name="login"
                        required={true}
                        value={login}
                        error={!isMailValid && login ? {
                            content: "Please enter a valid email address",
                            pointing: "below",
                        } : false}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setLogin(e.target.value)}
                    />
                </Form.Group>
                <Divider hidden/>
                <Form.Group>
                    <Form.Select
                        width={4}
                        placeholder="User role"
                        label="User role"
                        name="user_role"
                        selection
                        options={roleDropdownOptions}
                        value={role}
                        required={true}
                        onChange={(event: React.ChangeEvent<HTMLSelectElement>, data: PlainObject) => {
                            event.preventDefault();
                            setRole(data.value);
                        }}
                    />
                    <Form.Select
                        width={4}
                        value={gender}
                        label="Gender"
                        name="gender"
                        selection
                        options={options}
                        required={true}
                        onChange={(event: React.ChangeEvent<HTMLSelectElement>, data: PlainObject) => setGender(data.value)}
                    />
                    <Form.Input
                        width={4}
                        label="Office"
                        name="office"
                        value={office}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setOffice(e.target.value)}
                    />
                    <div style={{"paddingLeft": "7px", "paddingRight": "7px"}}>
                        <label>
                            Date of birth
                        </label>
                        <br/>
                        <DatePicker
                            selected={startDate}
                            onChange={(date: Date) => {
                                setStartDate(date)
                            }}
                            peekNextMonth
                            showMonthDropdown
                            showYearDropdown
                            dropdownMode="select"
                        />
                    </div>
                </Form.Group>
                <Divider hidden/>
                <Form.Group>
                    <Form.Input
                        width={4}
                        label="Address"
                        name="address"
                        value={address}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setAddress(e.target.value)}
                    />
                    <Form.Input
                        width={4}
                        label="Phone number"
                        name="telephone"
                        value={phone}
                        required={true}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPhone(e.target.value)}
                        error={!isPhoneValid && phone ? {
                            content: "Please enter a valid phone number",
                            pointing: "below",
                        } : false}
                    />
                    <Form.TextArea
                        label="About"
                        value={about}
                        width={8}
                        onChange={(e: React.ChangeEvent<HTMLTextAreaElement>, data: PlainObject) => setAbout(data.value)}
                    />

                </Form.Group>
                <Divider hidden/>
                <Form.Group widths="equal">
                    <Form.Input
                        label="Social number"
                        name="socialNumber"
                        value={socialNumber}
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSocialNumber(e.target.value)}
                    />
                </Form.Group>
                <Divider hidden/>
                <Button
                    floated="right"
                    size="medium"
                    onClick={() => history.push("/admin")}
                >
                    Back
                </Button>
                <Button
                    color="blue"
                    floated="right"
                    size="medium"
                    disabled={!isMailValid || !isPhoneValid}
                >
                    Save
                </Button>
            </Form>
        </Fragment>
    );
}

export default EditUserPage;

1 个答案:

答案 0 :(得分:2)

我认为您需要另一个 useEffect 来监视 userProfileData 上的更改。

现在您正在使用 userProfileData 初始化所有钩子状态变量,但在第一次传递时数据为空。

当商店更新时,userProfileData 值应该会改变,但该组件并未设置为对其执行任何操作。

const [firstName, setFirstName] = useState<string>(userProfileData.firstName);

如果您在下面还有一个调用 set 回调的钩子,它应该在商店执行后更新。

useEffect(() => {
setFirstName(userProfileData.firstName);
}, [userProfileData])'

如果您遇到以下情况,这可能会导致问题

  • 用户已输入信息
  • 商店更新

如果该实例是可能的,您可以在 useEffect 的开头添加逻辑,如果该字段已被更新,则不更新该字段。