挂钩setState不能充当基于类的组件

时间:2019-12-10 14:02:59

标签: reactjs react-hooks react-state-management

我尝试了具有更新状态的表单验证,但无法通过React挂钩进行。但是,基于类的组件。我可以正确做到

挂钩:

import React from "react";
import { Form, TextInput, Button } from "btt-ui";

const FormItem = Form.Item;

    const SimpleForm = () => {
  const [isRaso, setIsRaso] = React.useState(false);

  const handleSubmit = (e, error, values) => {
    e.preventDefault();
    if (!error) {
      alert(JSON.stringify(values));
    }
  };
  const checkRaso = (rule, value, callback) => {
    if (isRaso) {
      callback([new Error("Custom Requierd")]);
    } else {
      callback();
    }
  };
  const handleValuesChange = values => {
    if (values.field1 && values.field1.length) {
      setIsRaso(true);
      console.log(isRaso);
    } else {
      setIsRaso(false);
      console.log(isRaso);
    }
  };

  return (
    <Form
      onSubmit={handleSubmit}
      onValuesChange={values => handleValuesChange(values)}
    >
      <FormItem label="Field1">
        <TextInput
          name="field1"
          validation={[{ required: true }, { min: 2, max: 5 }]}
        />
      </FormItem>
      <FormItem label="Field2">
        {/* You can define custom error messages in a `message` property */}
        <TextInput
          name="field2"
          validation={[
            {
              validator: (rule, value, callback) =>
                checkRaso(rule, value, callback)
            }
          ]}
        />
      </FormItem>
      <FormItem>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
};

基于类:

 import React from "react";
 import { Form, TextInput, Button } from "btt-ui";

 const FormItem = Form.Item;

class SimpleForm2 extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.state = { isRaso: false };
  }

  handleSubmit(e, error, values) {
    e.preventDefault();
    if (!error) {
      // Do sth. with values
      alert(JSON.stringify(values));
    }
  }

  handleValuesChange(values) {
    if (values.field1 && values.field1.length) {
      this.setState({ isRaso: true });
      console.log(this.state.isRaso);
    } else {
      this.setState({ isRaso: false });
      console.log(this.state.isRaso);
    }
  }

  checkRaso(rule, value, callback) {
    if (this.state.isRaso) {
      callback([new Error("Custom Requierd")]);
    } else {
      callback();
    }
  }

  render() {
    return (
      <Form
        onSubmit={this.handleSubmit}
        onValuesChange={values => this.handleValuesChange(values)}
      >
        <FormItem label="Field1">
          <TextInput
            name="field1"
            validation={[{ required: true }, { min: 2, max: 5 }]}
          />
        </FormItem>
        <FormItem label="Field2">
          {/* You can define custom error messages in a `message` property */}
          <TextInput
            name="field2"
            validation={[
              {
                validator: (rule, value, callback) =>
                  this.checkRaso(rule, value, callback)
              }
            ]}
          />
        </FormItem>
        <FormItem>
          <Button type="primary" htmlType="submit">
            Submit
          </Button>
        </FormItem>
      </Form>
    );
  }
}

使用基于类的组件提交时

Image1:When on submit with class based component

带有钩子的onSubmit,不更新状态和验证字段 Image2:onSubmit with hooks,doesnt update state and validate field

React和ReactDom版本

  

“反应”:“ ^ 16.12.0”,
  “ react-dom”:“ ^ 16.12.0”,

1 个答案:

答案 0 :(得分:0)

Hooks的主要原因之一是避免弄乱bind方法和js this。另一种选择是改为使用hooksprops,因此尝试使用bind(this),尽管可能的是,我认为这不是最佳策略:

您可以使用useState挂钩执行类似的操作:

import React from 'react';
import { useState } from "react";
import { Form, Icon, Input, Button } from 'antd';

const SimpleForm = () => {
  const [isRaso, setIsRaso] = useState(false);
  const [fields, setfields] = useState(
    {
      field1: "",
      field2: "",
    }
  );

  const handleSubmit = (evt) => {
      evt.preventDefault();
      alert(`Field1: ${fields.field1} \nField2: ${fields.field2}\nIsRaso: ${isRaso}`);
      setfields({
        field1: "",
        field2: "",
      });
  }

  const handleValuesChanges = (event) => {
    setfields({
      ...fields,
      [event.target.name]: event.target.value,
    });
    if (fields.field1 && fields.field1.length) {
      setIsRaso(true);
    } else {
      setIsRaso(false);
    }
  };
  return (
    <Form
      onSubmit={handleSubmit}
      onChange={handleValuesChanges}
    >
        <Input
          name="field1"
          value={fields.field1}
        />

        <Input
          name="field2"
          value={fields.field2}
        />
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
    </Form>
  );
};

export default SimpleForm;

甚至是自定义钩子...

import React from 'react';
import { useState } from "react";
import { Form, Icon, Input, Button } from 'antd';


const useInput = initialValue => {
  const [value, setValue] = useState(initialValue);
  return {
    value,
    setValue,
    reset: () => setValue(""),
    bind: {
      value,
      onChange: event => {
        setValue(event.target.value);
      }
    }
  };
};


const SimpleForm = () => {
  const [isRaso, setIsRaso] = useState(false);
  const { value:field1, bind:bindfield1, reset:resetfield1 } = useInput('');
  const { value:field2, bind:bindfield2, reset:resetfield2 } = useInput('');

  const handleSubmit = (evt) => {
      evt.preventDefault();
      alert(`Field1: ${field1} \nField2: ${field2}\nIsRaso: ${isRaso}`);
      resetfield1();
      resetfield2();
  }

  const handleValuesChanges = (e) => {
    if (field1 && field1.length) {
      setIsRaso(true);
    } else {
      setIsRaso(false);
    }
  };
  return (
    <Form
      onSubmit={handleSubmit}
      onChange={handleValuesChanges}
    >
        <Input
          name="field1"
          {...bindfield1}
        />

        <Input
          name="field2"
          {...bindfield2}
        />
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
    </Form>
  );
};

export default SimpleForm;

我已简化了该问题以使其变得更容易,希望它对您有用。

这也可以为您提供帮助:https://rangle.io/blog/simplifying-controlled-inputs-with-hooks/


此外,在记录如下钩子时要小心:

    handleValuesChange(){
      setState({ isRaso: true });
      console.log(isRaso);
    }

因为它们可能不会立即从React Documentation更新:

  

setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用setState()之后立即读取this.state可能是一个陷阱...