reactjs - 如何将输入值从子表单组件传递到其父组件的状态以使用反应挂钩提交?
问题描述
我正在设置一个多步骤表单来处理使用 Next.js 和 Material-UI 登录。在signup.js
位于的页面中pages/signup.js
。我的多步骤表单已创建。在该页面中,定义了要显示为步骤内容的子组件,getStepContent(step)
并在其下方调用主组件SignInSide
。前进和后退的步骤也在signup.js
页面上定义。子表单组件仅包含输入。我正在尝试将输入到子组件表单输入中的数据传递给注册页面中父组件的状态,signup.js
以便我可以提交它。父组件和子组件都是功能组件,使用反应钩子进行状态。
我已经尝试将道具从父组件传递给子组件,然后将 TextField 组件的“值”定义为 {props.value} 并且当我在父组件中使用 console.log 值测试它时,它起作用了我看到了这些字母,但是没有名称:附加到它上面,它只是作为字母出现所以我尝试添加 [name]: event.target.value 但是当我尝试在输入中写入文本时字段它只是说 [Object object] 但是,在控制台中我可以看到 [Object object](在此处输入的插入字母),因此它记录了文本但不正确,并且输入的文本在输入框中不可见。
这就是步骤内容所在的位置。
const steps = ['Welcome', 'Information', 'Creative', 'Confirm'];
function getStepContent(step) {
const [value, setValue] = React.useState('');
//set state for returned input values
function handleChange(newValue) {
setValue(newValue);
}
switch (step) {
case 0:
return (
<div style={{ padding: '8em 0 4em' }}>
<Hero title='Welcome' paragraph="Let's get you signed up." />
</div>
);
case 1: // Form Components
return <CredentialsForm value={value} onChange={handleChange} />;
case 2:
return <CreativeForm />;
case 3:
return <Review />;
default:
throw new Error('Unknown step');
}
}
// Sign In Page
export default function SignInSide() {
const classes = useStyles();
const [activeStep, setActiveStep] = React.useState(0);
const [form, setForm] = React.useState(false);
// Forward and Back button functions, the buttons are defined here, in the parent page component.
const handleNext = () => {
setActiveStep(activeStep + 1);
};
const handleBack = () => {
setActiveStep(activeStep - 1);
};
const handleFormExtend = () => {
setForm(true);
setActiveStep(activeStep + 1);
};
return (
...
)
}
父组件是SignInSide
. 我正在使用材料-ui。可以在这里看到我使用的步进器表单的示例:https ://material-ui.com/getting-started/templates/checkout/它的类似代码,我只是将文本字段更改为概述并设置了道具的逻辑从父母传来的。
内部<CredentialsForm value={value} onChange={handleChange} />
组件。
export default function CredentialsForm(props) {
const classes = useStyles();
// Floating Form Label
const inputLabel = React.useRef(null);
const [labelWidth, setLabelWidth] = React.useState(0);
React.useEffect(() => {
setLabelWidth(inputLabel.current.offsetWidth);
}, []);
//Send input value to parent state
const handleChange = name => event => {
props.onChange({
[name]: event.target.value
});
};
return (
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component='h1' variant='h5'>
Who Are U?
</Typography>
<form className={classes.form} noValidate>
<Grid container spacing={2}>
<Grid item xs={2} md={2}>
<FormControl
margin='normal'
variant='outlined'
fullWidth
required
className={classes.formControl}
>
<InputLabel
ref={inputLabel}
htmlFor='outlined-userTitle-native-simple'
>
Title
</InputLabel>
<Select
native
value={props.value}
onChange={handleChange('title')}
labelWidth={labelWidth}
required
inputProps={{
name: 'title'
}}
>
<option value='' />
<option value={10}>Mr.</option>
<option value={20}>Ms.</option>
<option value={20}>Mrs.</option>
<option value={30}>Non-Binary</option>
</Select>
</FormControl>
</Grid>
<Grid item xs={5} md={5}>
<TextField
variant='outlined'
margin='normal'
required
fullWidth
value={props.value}
onChange={handleChange('firstName')}
id='first'
label='First Name'
name='firstname'
/>
</Grid>
</Grid>
</form>
</div>
);
}
预期:在用户输入时,子组件将输入保存在状态中并将其传递给父组件,以便它可以提交数据以进行注册。
实际:输入已成功传递给父级,但格式错误。它作为“[Object object](用户在此处键入的字母)”传递,并且在输入字段中,用户只能看到控制台中看到的 [Object object]。没有错误。
解决方案
你的问题在这里:
const handleChange = name => event => {
props.onChange({
[name]: event.target.value
});
};
你给你的props.onChange
函数一个对象,但是那个函数正在更新一个用字符串值初始化的状态钩子。然后,您将文本值设置为一个对象,而它曾经是一个字符串,为您提供看起来很奇怪的对象文本。
此外,您将所有表单值设置为与父状态相同的字符串。
要解决此问题,请将您的状态设置为对象而不是字符串。
在父母中:
const [values, setValues] = React.useState({title: '', firstName: ''});
....
function handleChange(newValue) {
setValues({...values, ...newValue});
}
....
return <CredentialsForm values={values} onChange={handleChange} />;
在儿童中:
<Select
native
value={props.values.title} // Change to this
onChange={handleChange('title')}
labelWidth={labelWidth}
required
inputProps={{
name: 'title'
}}
>
....
<TextField
variant='outlined'
margin='normal'
required
fullWidth
value={props.values.firstName} // Change to this
onChange={handleChange('firstName')}
id='first'
label='First Name'
name='firstname'
/>
推荐但不是必需的:我会去掉handleChange
表单组件中的函数,因为它并没有真正增加价值。然后props.onChange
直接从输入调用,并将您的父级更改handleChange
为:
const handleChange = name => event => {
setValues({...values, [name]: event.target.value});
}
推荐阅读
- android - 当 SMS 到达 Android oreo 时,如何使用广播接收器获得警报/通知?
- django - 如何访问字典键作为 django 模板中列表索引的索引
- javascript - 已部署的 iOS React Native 应用程序中的空白图像
- reactjs - React 中的 Axios GET 请求
- python - 我怎样才能使它更有效率?Python DNA 生成器
- ruby-on-rails - rspec 期望会根据现有的其他期望而变化
- php - LOCK TABLES 会导致 InnoDB 中的死锁吗?
- javascript - 热门在 Meteor 中为自定义域上的 Graphlql 请求设置 HTTP 标头
- html - 如何让我的激活表单与相对位置一起使用?
- reactjs - reduce(prev,curr)函数在react redux中返回未定义