如何在React中清除动态形式的输入值

时间:2019-06-23 13:13:23

标签: javascript reactjs

我有一个动态形式作为功能组件,它是通过基于类的组件生成的。我要设置重置按钮,以清除输入字段值并将状态设置为null数组。

此处提供完整代码: https://codesandbox.io/s/beautiful-archimedes-o1ygt

我想创建一个重置按钮,清除所有输入值并将Itemvalues数组初始化为null。 即使我将值设置为null,也不会清除输入字段。

但是,我面临的问题是,由于它是动态表单和功能组件,因此对于每个单独的表单字段都没有预定义的状态,因此很难将值设置为null。 有人可以帮忙吗,我长期以来一直坚持下去

4 个答案:

答案 0 :(得分:8)

以下是一个代码框,向您展示如何重置项目:https://codesandbox.io/s/romantic-heisenberg-93qi7

我还为您提供了有关如何使其与API数据一起使用的注释,请参见onChangeText()内的注释

问题是输入不像您推断的那样受状态控制。我们应该为您API中的每个项目创建一个更新的对象,并为其提供一个value属性。

index.js

import React from "react";
import ReactDOM from "react-dom";
import Cart from "./Cart";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      Items: [],
      itemvalues: [{}]
    };
    this.onChangeText = this.onChangeText.bind(this);
    this.getItems = this.getItems.bind(this);
    this.handleReset = this.handleReset.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.findFieldIndex = this.findFieldIndex.bind(this);
    this.trimText = this.trimText.bind(this);
  }

  getItems = () => {
    /*if the data is coming from an API, store it in an array then .map() over it.
     we can add a value prop to the object like:
      so you can do something like:

      const newItems = [...apiData].map((item) => {
        return {
          ...item,
          value: ""
        }
      })

      this.setState({
        Items: newItems
      })
     */

    this.setState({
      Items: [
        {
          name: "item1",
          description: "item1",
          group: "groupA",
          dtype: "str",
          value: ""
        },
        {
          name: "item2",
          description: "item2",
          group: "groupA",
          dtype: "str",
          value: ""
        },
        {
          name: "item3",
          description: "item3",
          group: "groupB",
          dtype: "str",
          value: ""
        },
        {
          name: "item4",
          description: "item4",
          group: "groupB",
          dtype: "str",
          value: ""
        }
      ]
    });
  };

  onChangeText = e => {
    const updatedItems = [...this.state.Items].map(item => {
      if (item.name === e.target.name) {
        return {
          ...item,
          value: e.target.value
        };
      } else {
        return item;
      }
    });

    const updatedItemValues = [...updatedItems].reduce((obj, curr) => {
      if (!obj[curr.group]) {
        obj[curr.group] = [];
      }
      obj[curr.group] = [...obj[curr.group], { [curr.name]: curr.value }];
      return obj;
    }, {});

    this.setState({
      ...this.state,
      Items: updatedItems,
      itemvalues: updatedItemValues
    });
  };

  findFieldIndex = (array, name) => {
    return array.findIndex(item => item[name] !== undefined);
  };
  trimText(str) {
    return str.trim();
  }

  handleReset = () => {
    const resetedItems = [...this.state.Items].map(item => {
      return {
        ...item,
        value: ""
      };
    });

    this.setState(
      {
        ...this.state,
        Items: resetedItems,
        itemvalues: []
      },
      () => console.log(this.state)
    );
  };

  handleSubmit = () => {
    console.log(this.state.itemvalues);
  };

  render() {
    return (
      <div>
        {
          <Cart
            Items={this.state.Items}
            getItems={this.getItems}
            handleSubmit={this.handleSubmit}
            handleReset={this.handleReset}
            onChangeText={this.onChangeText}
          />
        }
      </div>
    );
  }
}

Cart.js

import React, { useEffect } from "react";
import Form from "./Form";

const Cart = props => {
  useEffect(() => {
    props.getItems(props.Items);
  }, []);

  return (
    <div>
      <Form Items={props.Items} onChangeText={props.onChangeText} />

      <button onClick={props.handleSubmit}>Submit</button>
      <button onClick={props.handleReset}>Reset</button>
    </div>
  );
};

export default Cart;

Cart组件可以基本保持不变,我们不需要将props.items传递给useEffect()依赖项。

Form.js

import React from "react";

const Form = props => {
  return (
    <div>
      {props.Items.map(item => {
        return (
          <input
            name={item.name}
            placeholder={item.description}
            data-type={item.dtype}
            data-group={item.group}
            onChange={e => props.onChangeText(e)}
            value={item.value}
          />
        );
      })}
    </div>
  );
};
export default Form;

现在在Form组件中,我们为每个输入提供一个值prop,该属性连接到我们最上层父组件状态的项目。

几乎所有您需要重置的值。

答案 1 :(得分:3)

查看是否适合您

Working example on CodeSandbox

enter image description here

由于您已经在代码的一部分中使用了钩子,因此我已经使用钩子将我的类转换为功能组件(我的建议:学习钩子,而不必考虑类组件)。

我已经为您的value添加了INITIAL_STATE属性,因此它将保留每个inputItem的输入值。

完整代码:

index.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import FormV2 from "./FormV2";

import "./styles.css";

function App() {
  const INITIAL_STATE = [
    {
      name: "item1",
      description: "item1",
      group: "groupA",
      dtype: "str",
      value: "" // ADDED VALUE PROPERTY TO KEEP THE INPUT VALUE
    },
    {
      name: "item2",
      description: "item2",
      group: "groupA",
      dtype: "str",
      value: ""
    },
    {
      name: "item3",
      description: "item3",
      group: "groupB",
      dtype: "str",
      value: ""
    },
    {
      name: "item4",
      description: "item4",
      group: "groupB",
      dtype: "str",
      value: ""
    }
  ];

  const [inputItems, setInputItems] = useState(INITIAL_STATE);

  function handleChange(event, index) {
    const newValue = event.target.value;
    setInputItems(prevState => {
      const aux = Array.from(prevState);
      aux[index].value = newValue;
      return aux;
    });
  }

  function handleReset() {
    console.log("Reseting Form to INITIAL_STATE ...");
    setInputItems(INITIAL_STATE);
  }

  function handleSubmit() {
    inputItems.forEach(item =>
      console.log(
        "I will submit input: " + item.name + ", which value is: " + item.value
      )
    );
  }

  return (
    <FormV2
      handleSubmit={handleSubmit}
      handleReset={handleReset}
      handleChange={handleChange}
      inputItems={inputItems}
    />
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

FormV2.js

import React from "react";

function FormV2(props) {
  const formInputItems = props.inputItems.map((item, index) => (
    <div key={item.name}>
      {item.name + ": "}
      <input
        type="text"
        data-type={item.dtype}
        data-group={item.group}
        placeholder={item.description}
        value={item.value}
        onChange={event => props.handleChange(event, index)}
      />
    </div>
  ));

  return (
    <React.Fragment>
      <form>{formInputItems}</form>
      <button onClick={props.handleSubmit}>Submit</button>
      <button onClick={props.handleReset}>Reset</button>
      <div>State: {JSON.stringify(props.inputItems)}</div>
    </React.Fragment>
  );
}

export default FormV2;

答案 2 :(得分:2)

为了控制我假定是输入字段的子组件(项)的值,您需要从其父组件传递其值。因此,您的每个商品都会有一个item.value,它以父组件的状态存储。

这意味着您可以在父组件中定义一个方法,该方法清除其在其状态下存储的所有项目值。 可能看起来像

resetInputs = () => {
    this.setState({
        inputFields: this.state.inputFields.map(inputField => {
            ...inputField,
            value: ''
        }
    })
}

此外,您还需要编写想要哪种代码才能使代码正常工作,例如输入。

因此,您最终获得的共享子组件代码如下所示:

const Form = (props) => {
    return (
    <div>
        {props.Items.map(item => (
          <input
            name={item.name}
            value={item.value}
            placeholder={item.description}
            onChange={e => props.onChangeText(e)}
          /> 
        )
        )}
      </div> 
    );
}
export default Form 

答案 3 :(得分:2)

您要管理未知数量N个项目的状态,一种实现方法是管理包含所有状态的单个对象,例如setValuesManager管理N输入并单击button重置其状态:

function TextAreaManager() {
  const [valuesManager, setValuesManager] = useState([...items]);
  return (
    <Flexbox>
      {valuesManager.map((value, i) => (
        <TextBoxItem
          key={i}
          value={value}
          onChange={e => {
            valuesManager[i] = e.target.value;
            setValuesManager([...valuesManager]);
          }}
        />
      ))}
      <PinkButton
        onClick={() =>
          setValuesManager([...Array(valuesManager.length).fill('')])
        }
      >
        Reset All
      </PinkButton>
    </Flexbox>
  );
}

演示:

Edit OS Q 556724228 - Manage dynamic form state

相关问题