如何更新自定义挂钩值

时间:2020-04-20 09:17:27

标签: reactjs typescript redux react-hooks

我已经开始学习打字稿,并对新的Web项目做出反应。我在管理自己制作的自定义钩子的初始值时遇到一些问题。无法胜任此功能。从API提取数据后,应如何更新 nameInput 挂钩。例如,如果我在 useTextInput 中将自定义字符串作为初始值传递,那么一切都很好,但是问题是当我首先传递未定义的值(从API提取数据时)和传递后的值时已下载,似乎没有更新。

我的问题是,如何通过getUser()方法中的API作为userAccount.firstName来自API的值来正确更新AccountInput inputValue值,而女巫依赖于nameInput,在useTextInput中的初始值之后女巫不会更新。

Account.tsx

import React, { useEffect, useState} from 'react';
import { connect } from 'react-redux';
import { IApplicationState } from '../../store';
import { actionCreators, reducer, AccountStatusEnum } from '../../store/Account';
import { MDBBtn, MDBInput } from 'mdbreact';
import { AccountInput } from './child-components';
import { useTextInput } from '../../hooks';

type AccountProps = ReturnType<typeof reducer> & typeof actionCreators;

const Account: React.FC<AccountProps> = ({ getUser, resetState, userAccount, status }) => {
    const nameInput = useTextInput(userAccount.firstName);
    const [isInputInvalid, setIsInputInvalid] = useState<boolean>(false);
    useEffect(() => {
        getUser();
    }, []);

        return (
            <React.Fragment>
                <div className="mt-3 container border border-light">
                    <h5 className="secondary-heading font-weight-bold pt-3 pl-5">User info</h5>
                    <div className="row">
                        <AccountInput
                            textInput={nameInput}
                            typeInput="text"
                            labelInput="Your name & surename"
                            isInputInvalid={isInputInvalid}
                        />
                    </div>
                </div>
            </React.Fragment>
        );
};

const mapStateToProps = (state: IApplicationState) => state.acc;

export default connect(mapStateToProps, actionCreators)(Account as any);

AccointInput.tsx

import React, { Fragment, useEffect, useState } from 'react';
import { TextInput } from '../../../hooks';
import { MDBInput } from 'mdbreact';

type AccountInputProps = {
    readonly textInput: TextInput;
    readonly isInputInvalid: boolean;
    readonly typeInput: string;
    readonly labelInput: string;
};

const AccountInput = React.memo<AccountInputProps>(({ textInput, isInputInvalid, typeInput, labelInput }) => {
    const { hasValue, bindToInput } = textInput;
    return (
        <Fragment>
            <div className="col-sm w-100 px-5">
                <MDBInput hint={textInput.value} {...bindToInput} type={typeInput} label={labelInput} />
            </div>
        </Fragment>
    );

});

AccountInput.displayName = 'AccountInput';

export default AccountInput;

useTextInput.ts

import { useState, useCallback, useMemo, FormEvent } from 'react';

export type TextInputType = 'text' | 'password';

export type TextInput = {
    value: string;
    hasValue: boolean;
    clear: () => void;
    bindToInput: {
        value: string;
        type: TextInputType;
        onChange: (e: FormEvent<HTMLInputElement>) => void;
    };
};

export const useTextInput = (initial: string = '', type: TextInputType = 'text'): TextInput => {
    const [value, setValue] = useState<string>(initial);
    const clear = useCallback((): void => setValue(''), []);
    const onChange = useCallback((e: FormEvent<HTMLInputElement>): void => setValue(e.currentTarget.value), []);

    return useMemo<TextInput>(
        () => ({
            value,
            clear,
            hasValue: !!(value && value.trim()),
            bindToInput: {
                type,
                value,
                onChange,
            },
        }),
        [value, type, onChange, clear],
    );
};

1 个答案:

答案 0 :(得分:2)

我不确定自定义钩子如何处理承诺,但是通常当您要将async值传递给useState时,您会执行以下操作:

const useTextInput = (initial) => {
  const [value, setValue] = useState(initial);

  useEffect(() => {
    setValue(initial);
  }, [initial]);
};

useEffect更改时,您可以使用initial更新状态值。这种情况适合您吗?