类型'(props:Props)=>元素'不能分配给带有React-final-form

时间:2019-09-09 11:43:15

标签: reactjs typescript material-ui react-final-form

我是初学者打字,我正尝试使用React-Final-FormTypescript创建一个注册表单。所以我创建了我的表单,描述如下:

import React from "react";
import Button from "@material-ui/core/Button";
import { Form, Field } from "react-final-form";
import { makeStyles, Theme, createStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import PasswordField from "../../components/Password";
import TextField from "../../components/TextField";
import { validate, submit } from "./validation";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    container: {
      padding: 16,
      margin: "auto",
      maxWidth: 600
    },
    paper: {
      padding: 16
    },
    item: {
      marginTop: 16
    }
  })
);

const SignUp = () => {
  const classes = useStyles();

  return (
    <div className={classes.container}>
      <Typography>SignUp Form</Typography>
      <Form
        onSubmit={submit}
        validate={validate}
        render={({ handleSubmit, form, submitting, pristine }) => (
          <form onSubmit={handleSubmit}>
            <Paper className={classes.paper}>
              <Grid container alignItems='flex-start' spacing={2}>
                <Grid item xs={6}>
                  <Field
                    fullWidth
                    required
                    name='Username'
                    component={TextField}
                    type='text'
                    label='Username'
                  />
                </Grid>
                <Grid item xs={6}>
                  <Field
                    fullWidth
                    required
                    name='Email'
                    component={TextField}
                    type='text'
                    label='Email'
                  />
                </Grid>
                <Grid item xs={6}>
                  <Field
                    fullWidth
                    required
                    name='Password'
                    component={PasswordField}
                    type='password'
                    label='Password'
                  />
                </Grid>
                <Grid item className={classes.item}>
                  <Button
                    type='button'
                    variant='contained'
                    onClick={form.reset}
                    disabled={submitting || pristine}
                  >
                    Reset
                  </Button>
                </Grid>
                <Grid item className={classes.item}>
                  <Button
                    variant='contained'
                    color='primary'
                    type='submit'
                    disabled={submitting}
                  >
                    Submit
                  </Button>
                </Grid>
              </Grid>
            </Paper>
          </form>
        )}
      />
    </div>
  );
};

export default SignUp;

需要TextFieldPassword这两个组合符:

TextField.tsx:

import React from "react";
import { makeStyles, Theme, createStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    textField: {
      marginLeft: theme.spacing(1),
      marginRight: theme.spacing(1)
    }
  })
);

interface Props {
  label: string;
  value: string;
  handleChange: () => {};
  type: string;
}

const SimpleTextField = (props: Props) => {
  const classes = useStyles();
  const { label, value, handleChange, type } = props;

  return (
    <TextField
      id='outlined-name'
      label={label}
      className={classes.textField}
      value={value}
      onChange={handleChange}
      type={type}
      margin='normal'
      variant='outlined'
    />
  );
};

export default SimpleTextField;

但是tslint返回此错误:

Type '(props: Props) => Element' is not assignable to type '"textarea" | "input" | "select" | ComponentClass<FieldRenderProps<any, HTMLElement>, any> | FunctionComponent<FieldRenderProps<any, HTMLElement>> | undefined'.
  Type '(props: Props) => Element' is not assignable to type 'FunctionComponent<FieldRenderProps<any, HTMLElement>>'.
    Types of parameters 'props' and 'props' are incompatible.
      Type 'FieldRenderProps<any, HTMLElement> & { children?: ReactNode; }' is missing the following properties from type 'Props': label, value, handleChange, type  TS2322

    44 |                     required
    45 |                     name='Username'
  > 46 |                     component={TextField}
       |                     ^
    47 |                     type='text'
    48 |                     label='Username'
    49 |                   />

我试图通过修改如下代码来更改TextField的返回值:

import React from "react";
import { makeStyles, Theme, createStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    textField: {
      marginLeft: theme.spacing(1),
      marginRight: theme.spacing(1)
    }
  })
);

interface Props {
  label: string;
  value: string;
  handleChange: () => {};
  type: string;
}

const SimpleTextField = (props: Props) => {
  const classes = useStyles();
  const { label, value, handleChange, type } = props;

  return (
    <TextField
      id='outlined-name'
      label={label}
      className={classes.textField}
      value={value}
      onChange={handleChange}
      type={type}
      margin='normal'
      variant='outlined'
    />
  );
};

const TextFieldWrapper = (props: Props) => {
   return(
     <>
      <SimpleTextField {...props}/>
     </>
   )
}

export default TextFieldWrapper;

但是仍然会遇到同样的问题。

2 个答案:

答案 0 :(得分:0)

'FieldRenderProps<any, HTMLElement> & { children?: ReactNode; }'

没有您在prop中定义的字段。父组件是否会将您定义的道具传递给组件?

答案 1 :(得分:0)

import React from "react";
import Button from "@material-ui/core/Button";
import { Form, Field } from "react-final-form";
import { makeStyles, Theme, createStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import PasswordField from "../../components/Password";
import TextField from "../../components/TextField";
import { validate, submit } from "./validation";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    container: {
      padding: 16,
      margin: "auto",
      maxWidth: 600
    },
    paper: {
      padding: 16
    },
    item: {
      marginTop: 16
    }
  })
);

const SignUp = () => {
  const classes = useStyles();

  return (
    <div className={classes.container}>
      <Typography>SignUp Form</Typography>
      <Form
        onSubmit={submit}
        validate={validate}
        render={({ handleSubmit, form, submitting, pristine }) => (
          <form onSubmit={handleSubmit}>
            <Paper className={classes.paper}>
              <Grid container alignItems='flex-start' spacing={2}>
                <Grid item xs={6}>
                  <Field fullWidth required name='Username'>
                    {props => (
                      <TextField
                        label='Username'
                        type='text'
                        value={props.input.value}
                        onChange={props.input.onChange}
                      />
                    )}
                  </Field>
                </Grid>
                <Grid item xs={6}>
                  <Field fullWidth required name='Email'>
                    {props => (
                      <TextField
                        label='Email'
                        type='email'
                        value={props.input.value}
                        onChange={props.input.onChange}
                      />
                    )}
                  </Field>
                </Grid>
                <Grid item xs={6}>
                  <Field fullWidth required name='Password'>
                    {props => (
                      <PasswordField
                        label='Password'
                        type='password'
                        value={props.input.value}
                        onChange={props.input.onChange}
                      />
                    )}
                  </Field>
                </Grid>
                <Grid item className={classes.item}>
                  <Button
                    type='button'
                    variant='contained'
                    onClick={form.reset}
                    disabled={submitting || pristine}
                  >
                    Reset
                  </Button>
                </Grid>
                <Grid item className={classes.item}>
                  <Button
                    variant='contained'
                    color='primary'
                    type='submit'
                    disabled={submitting}
                  >
                    Submit
                  </Button>
                </Grid>
              </Grid>
            </Paper>
          </form>
        )}
      />
    </div>
  );
};

export default SignUp;