繁体   English   中英

React Hooks TypeScript 事件和状态类型

[英]React Hooks TypeScript event and state types

React.js 的状态和事件有哪些类型?

在我下面的代码中,我只能通过使用type: any使其工作,但这只是一个 hack。 我怎样才能为他们使用正确的类型?

在我的自定义钩子中:

如果我使用function useFormFields(initialState: object) ,我会得到:

// value={inputs.item} error:
Property 'item' does not exist on type 'object'.ts(2339)
// onChange function error:
(JSX attribute) onChange: object
No overload matches this call.

如果我使用function(event: React.FormEvent) (这是真的),我有这个错误:

Property 'id' does not exist on type 'EventTarget'.ts(2339)

如果我使用function(event: object) ,则会出现此错误:

Property 'target' does not exist on type 'object'.ts(2339)

这很奇怪,因为下面我使用const handleSubmitItem = (event: React.FormEvent)并且它有效。

我找到的答案(比如这个)对我不起作用,因为Property 'id' does not exist on type 'EventTarget'

import React, {useState} from 'react';
import TextField from '@material-ui/core/TextField';
import IconButton from '@material-ui/core/IconButton';
import AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';

/**
 * Custom hooks for input fields.
 * @param initialState initialState for Input Fields
 */
function useFormFields(initialState: any) {
    const [inputs, setValues] = useState(initialState);

    return [
        inputs,
        function(event: any) {
            setValues({
                ...inputs,
                [event.target.id]: event.target.value
            });
        }
    ];
}

export default function FormPropsTextFields() {
    const [inputs, handleInputChange] = useFormFields({
        item: '',
        quantity: '',
        store: ''
    });

    const handleSubmitItem = (event: React.FormEvent) => {
        event.preventDefault();
        console.log(inputs);
    };

    return (
        <form 
            className={classes.root} 
            noValidate autoComplete="off"
            onSubmit={handleSubmitItem}
        >
            <div>
                <TextField 
                    required id="item" 
                    label="Item" 
                    value={inputs.item}
                    onChange={handleInputChange}
                />
                <TextField
                    id="quantity"
                    label="Quantity"
                    type="number"
                    value={inputs.quantity}
                    onChange={handleInputChange}
                    InputLabelProps={{
                        shrink: true,
                    }}
                />
                <TextField 
                    id="store" 
                    label="Store" 
                    type="search"
                    value={inputs.store}
                    onChange={handleInputChange}
                />
                <IconButton 
                    type="submit"
                    color="primary" 
                    aria-label="add to shopping cart"
                >
                    <AddShoppingCartIcon />
                </IconButton>
            </div>
        </form>
    );
}

我在您找到的解决方案中进行了一些更正。 希望能帮助到你!

import React, {useState} from 'react';
import TextField from '@material-ui/core/TextField';
import IconButton from '@material-ui/core/IconButton';
import AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';

/**
 * Custom hooks for input fields.
 * @param initialState initialState for Input Fields
 */

export interface MyModel {
    item: string
    quantity: string
    store: string
}

function useFormFields<T>(initialState: T): [T, (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => void] {
    const [inputs, setValues] = useState<T>(initialState);

    return [
        inputs,
        function (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) {
            setValues({
                ...inputs,
                [event.target.id]: event.target.value
            });
        }
    ];
}

export default function FormPropsTextFields() {
    const [inputs, handleInputChange] = useFormFields<MyModel>({
        item: '',
        quantity: '',
        store: ''
    });

    const handleSubmitItem = (event: React.FormEvent) => {
        event.preventDefault();
        console.log(inputs);
    };

    return (
        <form 
            className={classes.root} 
            noValidate autoComplete="off"
            onSubmit={handleSubmitItem}
        >
            <div>
                <TextField 
                    required id="item" 
                    label="Item" 
                    value={inputs.item}
                    onChange={handleInputChange}
                />
                <TextField
                    id="quantity"
                    label="Quantity"
                    type="number"
                    value={inputs.quantity}
                    onChange={handleInputChange}
                    InputLabelProps={{
                        shrink: true,
                    }}
                />
                <TextField 
                    id="store" 
                    label="Store" 
                    type="search"
                    value={inputs.store}
                    onChange={handleInputChange}
                />
                <IconButton 
                    type="submit"
                    color="primary" 
                    aria-label="add to shopping cart"
                >
                    <AddShoppingCartIcon />
                </IconButton>
            </div>
        </form>
    );
}

由于每个组件可能不同,您需要自己定义 state 和 props 类型。 有一些为 react 定义的基本类型(例如,因为每个组件都可能有children组件),但正如我所说,您需要定义自己的类型。

功能组件的示例:

const App: React.FC<{ message: string }> = ({ message }) => (
  <div>{message}</div>
);

上面的例子也可以这样写:

type MyType = { message: string }
const App: React.FC<MyType> = ({ message }) => (
  <div>{message}</div>
);

进一步阅读:

https://github.com/typescript-cheatsheets/react-typescript-cheatsheet#section-2-getting-started

将军们! 答案!

希望能帮助到你!


import IconButton from '@material-ui/core/IconButton';
import TextField from '@material-ui/core/TextField';
import AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';
import React, { useState } from 'react';

export interface MyModel {
    item: string;
    quantity: string;
    store: string;
 }

/**
 * Custom hooks for input fields.
 * @param initialState initialState for Input Fields
 **/
function useFormFields<T>(initialState: T) {
    const [inputs, setValues] = useState(initialState);

    return [
        inputs,
        function(event: React.FormEvent) {
            const {name, value} = event.currentTarget;
            setValues({
                ...inputs,
                [name]: value
            });
        }
    ];
}

export default function FormPropsTextFields() {
    const [inputs, handleInputChange] = useFormFields<MyModel>({
        item: '',
        quantity: '',
        store: '',
    });

    const handleSubmitItem = (event: React.MouseEvent<HTMLButtonElement>) => {
        event.preventDefault();
        /***
           make sure to have whatever attribute you want in the "html tag"
        */
        const { name, value } = event.currentTarget;
        console.log(inputs);
    };

    return (
        <form
            className={classes.root}
            noValidate autoComplete="off"
        >
            <div>
                <TextField
                    required id="item"
                    label="Item"
                    name="Item"
                    value={inputs.item}
                    onChange={handleInputChange}
                />
                <TextField
                    id="quantity"
                    label="Quantity"
                    name="Quantity"
                    type="number"
                    value={inputs.quantity}
                    onChange={handleInputChange}
                    InputLabelProps={{
                        shrink: true,
                    }}
                />
                <TextField
                    id="store"
                    label="Store"
                    name="Store"
                    type="search"
                    value={inputs.store}
                    onChange={handleInputChange}
                />
                <IconButton
                    type="button"
                    color="primary"
                    aria-label="add to shopping cart"
                    onClick={handleSubmitItem}
                >
                    <AddShoppingCartIcon />
                </IconButton>
            </div>
        </form>
    );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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