如何获得动态/多个字段的值与React的formsubmit ?



我有一个表单,用户可以在其中添加文本字段以添加更多项目,当他们提交时,我正在努力将项目从表单中取出。

Textfields是由一个组件函数创建的(如下所示),并且整个表单不包含在一个函数中,正如我在许多示例中看到的那样,这意味着我不能简单地将值存储为状态并稍后读取它们(我认为…?)。

这些字段是用以下代码生成的:

const itemNameTextFields = () => {
const [itemNames, setItemNames] = React.useState(['']);
const addItemNameField = () => setItemNames([...itemNames, '']);
const handleInputChange = (i, e) => {
const values = [...itemNames];
values[i] = e.target.value;
setItemNames(values);
}
return (
itemNames.map((itemName, i) => (
<Box component='span' key={`item_${i}`} sx={{display: 'flex', flexWrap: 'wrap'}}>
<TextField
value={itemName}
onChange={e => handleInputChange(i, e)}
label={`Item ${i+1}`}
name={`item_${i}`}
className={classes.itemName}
/>
{itemNames.length-1 === i &&
<Button
endIcon={<Icon icon={plusCircleOutline} />}
onClick={addItemNameField}
>
<small>Add another</small>
</Button>
}
</Box>
));
);
}

处理提交的表单的代码是这样的:

const handleSubmit = e => {
e.preventDefault();
let obj = {
/* ... */
name                : e.target['name'].value || '',
items               : [] //this is what I am missing
};
console.log(obj);
}

然而,这可能不是一个好的方法。

我想要实现的要么是:

  • 对于obj中的items,是一个包含第一个代码块中每个Textfield值的数组。如obj ={项目:("item1","第二条",/]}或
  • obj单独包含每个项目。如obj = {item_1: item1, item_2:"项"2,/}

理想情况下,不需要任何第三方库就可以找到解决方案。

我想过的一个可能的"解决方案"是有一个隐藏的输入元素,其状态包含数组,然后在formsubmit上获取该值,而不是每个单独的字段,但这会导致数组被"发送"为逗号分隔的列表,这可能会导致问题,如果任何值中有逗号。

或者,找到一种方法将每个输入字段的值传递给handleSubmit(也许通过道具?)也可以工作,但我不太确定如何实现这一点。

谢谢:)

您可以添加一个redux store来传递如下参数;

const React = window.React;
const ReactDOM = window.ReactDOM;
const {Box, Button, TextField} = window.MaterialUI;
const Redux = window.Redux;


function itemReducer(state = [], action) {
switch (action.type) {
case 'SET':
let tmp = [...state];
tmp[action.index] = action.item;
return state = tmp;
default:
return state;
}
}

const store = Redux.createStore(itemReducer, [])

const handleSubmit = e => {
e.preventDefault()
let obj = {
name                : e.target.innerHTML || '',
items               : store.getState() 
}
console.log(obj)
}

const App = () => {

const itemNameTextFields = () => {

const [itemNames, setItemNames] = React.useState([''])

const addItemNameField = () => {
setItemNames([...itemNames, '']);
}

const handleInputChange = (i, e) => {
store.dispatch({
type:"SET",
index:i,
item:e.target.value
});
const values = [...itemNames]
values[i] = e.target.value
setItemNames(values)
}

return (
itemNames.map((itemName, i) => (
<Box component='span' key={"item_" + i} sx={{display: 'flex', flexWrap: 'wrap', marginBottom:1}}>
<TextField
value={itemName}
onChange={e => handleInputChange(i, e)}
label={"Item " + i}
name={"item" + i}
variant="outlined"
fullWidth
/>
{itemNames.length-1 === i &&
<Button
size='small'
onClick={addItemNameField}
disabled={!itemNames[itemNames.length-1].length > 0}
style={{marginLeft:4}}
>
<small>Add another</small>
</Button>
}
</Box>
))
)
}

return itemNameTextFields();
}

ReactDOM.render(
<div><App/><Button onClick={handleSubmit}>Submit</Button></div>, 
document.getElementById('root')
);
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/redux@4.1.1/dist/redux.js"></script>
<script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.development.js"></script>
<div id="root"></div>

可以跟踪呈现表单的元素中的项,换句话说,就是将usestate移动到表单元素中。将状态值和setter传递给子文本域元素,并调用状态变量,而不是让这些元素拥有自己的状态。

你应该能够访问该状态在你的onsubmit

有时候react的行为很神秘。您可以尝试直接从itemNames数组中添加映射值和名称。

const handleInputChange = (i, e) => {
//const values = [...itemNames];
//values[i] = e.target.value;
itemNames[i] = e.target.value
setItemNames([...itemNames]);
}

通过这种方式,你可以更新itemNames数组。

我最终解决了这个问题,方法是在主表单组件中管理状态,而不是在每个单独的表单元素组件中管理状态,然后将useState函数传递给每个组件,如下所示:

const FormElement = ({value, onChange)} => {
const handleChange = e => {
onChange(e.target.value)
}
return (
<TextField
{...props}
onChange={handleChange}
value={value}
/>
)
}
const AddNewEventForm = () => {
const classes = useStyles()
const [formElementValue, setFormElementValue] = React.useState('')

const handleSubmit = e => {
e.preventDefault()
/* ... */
console.log(formElementValue)
}
return (
<form onSubmit={handleSubmit}>
<Box>
<FormElement value={formElementValue} onChange={setFormElementValue} />
</Box>
<Box>
<Button type="submit">
Submit
</Button>
</Box>
</form>
)
}

通过这种方式处理状态,来自子组件的数据可以被父函数中的handleSubmit访问。

最新更新