我目前正在使用带有react-hooks的react-js编写注册页面,但我仍在学习,因此,如果这是一个非常简单的问题,请原谅。
我有一个用钩子在功能组件中编写的signup.js。 signup.js导入“ EmailTextField”,“ PasswordTextField”,“ NameTextField”,“ CellPhoneTextField” ...其中的组件也用钩子编写在功能组件中。
我将所有这些文本字段都作为单独的组件来简化代码,因为我需要对每个文本字段进行许多不同的检查。 (并且在signup.js页面中包含所有这些字段会产生很长的代码)
在signup.js的过程结束时,我想获取其所有子组件(所有这些文本字段)状态的状态(无论用户是否登录良好)。但是我不确定如何将这些文本字段中的状态(或变量)传递到signup.js。
我知道redux可以管理状态,但是有没有Redux可以实现呢?
谢谢。
我创建了一个CodeSandbox Sample,其中包含最少的示例代码。
在这里,我在EmailTextfield
中使用apptest.js
组件。我想从isValid
获得EmailTextfield
上的apptest.js
状态,以便我可以确保在用户注册之前验证所有字段。
'./ components / UI / Textfield / EmailTextField.js'
import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
export const EmailTextField = props => {
const [value, setValue] = useState("");
const [helperText, setHelperText] = useState(
"Email address will be used as your username."
);
const [isValid, setIsValid] = useState("true");
const handleOnChangeEmailAddress = event => {
// Email Validation logic
if (true) {
setIsValid(true);
} else {
setIsValid(false);
}
};
return (
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="email address"
error={!isValid}
helperText={helperText}
name="email"
autoComplete="email"
margin="dense"
onBlur={handleOnChangeEmailAddress}
/>
</Grid>
);
};
export default EmailTextField;
'aptest.js'
import React from "react";
import CssBaseline from "@material-ui/core/CssBaseline";
import Grid from "@material-ui/core/Grid";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
import { EmailTextField } from "./components/UI/Textfield/EmailTextField";
const useStyles = makeStyles(theme => ({
"@global": {
body: {
backgroundColor: theme.palette.common.white
}
},
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center"
},
mainBox: {
// margin: '200px',
width: "550px",
textAlign: "left",
boxShadow: "0 2px 3px #ccc",
border: "1px solid #eee",
padding: "40px 70px 50px 70px",
boxSizing: "border-box"
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(3)
}
}));
const Apptest = props => {
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<div className={classes.mainBox}>
<form className={classes.form} noValidate>
<Grid container spacing={2}>
<EmailTextField />
</Grid>
</form>
</div>
</div>
</Container>
);
};
export default Apptest;
答案 0 :(得分:2)
我想到的是一个非常粗糙的实现。
“输入”字段周围应该有一致的数据模型。该数据模型应该是该特定输入字段的唯一事实来源。它应该能够判断该特定字段是否被触摸,是否有错误,是否原始,它的价值以及所有这些东西。
因此,假设您拥有这样的内容:
errors: [],
onChange: false,
pristine: true,
touched: false,
value,
我们称它为StateChangeEvent
。
现在,每个Input字段都将具有处理更改和模糊等事件的处理程序。在这里,单个组件将更新StateChangeEvent。这些方法最终将使用StateChangeEvent
作为参数调用回调函数。
这样,父母将知道其中一个字段发生了变化,并且它可以做出相应的响应。
在父组件中,要启用表单上的“提交按钮”,我们还可能会有副作用,它将更新表单的整体状态。像这样:
useEffect(() => {
const isValid = !fieldOne.onChange &&
fieldOne.errors.length === 0 &&
fieldOne.value.length !== 0 &&
!fieldTwo.onChange &&
fieldTwo.errors.length === 0 &&
fieldTwo.value.length !== 0 &&
...;
setIsFormValid(isValid);
}, [fieldOne, fieldTwo, ...]);
我确定这不是一个完整的解决方案。但我相信它会帮助您入门。
更新:
根据您提供的CodeSandbox,可以执行以下操作:
import ...
const useStyles = makeStyles(theme => ({ ... }));
const Apptest = props => {
const classes = useStyles();
const [isInvalid, setIsInvalid] = useState(true);
const handleStateChange = updatedState => {
console.log("updatedState: ", updatedState);
updatedState.errors.length === 0 ? setIsInvalid(false) : setIsInvalid(true);
};
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<div className={classes.mainBox}>
<form className={classes.form} noValidate>
<Grid container spacing={2}>
<EmailTextField onStateChange={handleStateChange} />
</Grid>
<Button
variant="contained"
color="primary"
disabled={isInvalid}
className={classes.button}
>
Submit
</Button>
</form>
</div>
</div>
</Container>
);
};
export default Apptest;
在EmailTextField
组件中:
import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
export const EmailTextField = props => {
const { onStateChange } = props;
const [state, setState] = useState({
errors: [],
onChange: false,
pristine: true,
touched: false,
value: null
});
const helperText = "Email address will be used as your username.";
const handleBlur = event => {
// Email Validation logic
const matches = event.target.value.match(
`[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}`
);
if (matches) {
const updatedState = {
...state,
touched: true,
value: event.target.value,
errors: []
};
setState(updatedState);
onStateChange(updatedState);
} else {
const updatedState = {
...state,
touched: true,
value: event.target.value,
errors: ["Please enter a valid email"]
};
setState(updatedState);
onStateChange(updatedState);
}
};
return (
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="email address"
error={state.errors.length > 0}
helperText={state.errors.length > 0 ? state.errors[0] : helperText}
name="email"
autoComplete="email"
margin="dense"
onBlur={handleBlur}
/>
</Grid>
);
};
export default EmailTextField;
这是您推荐的Working CodeSandbox Sample。
答案 1 :(得分:0)
我知道了,对您的迟到表示抱歉。我睡着了。基本上onBlur()
会进行回调,现在在这种情况下,您需要将输入框中的值传递给回调,以便可以访问用户输入的值。另一种方法是使用onChange()
来跟踪更改并进行设置,以便在调用onblur
时可以检查value
,然后可以执行验证。
因此,您只需要像target
一样将事件的callback
值传递给onBlur={(e) => handleOnChangeEmailAddress(e.target.value)}
,然后就可以访问method中的值。我已经重构了您在沙箱中共享的代码。在下面找到我所做的摘要。
import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
export const EmailTextField = props => {
const [value, setValue] = useState("");
const [helperText, setHelperText] = useState(
"Email address will be used as your username."
);
const [isValid, setIsValid] = useState("true");
const handleOnChangeEmailAddress = value => {
// Email Validation logic
if (!value) {
setIsValid(true);
} else {
setIsValid(false);
}
console.log(isValid)
};
return (
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="email address"
error={!isValid}
helperText={helperText}
name="email"
autoComplete="email"
margin="dense"
onBlur={(e) => handleOnChangeEmailAddress(e.target.value)}
/>
</Grid>
);
};
export default EmailTextField;
希望对您有帮助。.如果您有任何问题,请随时提出问题。
答案 2 :(得分:0)
从您的codeandbox示例中,您似乎差不多就在那儿,只需要传递onStateChange
函数作为道具:
<EmailTextField onStateChange={onStateChange} />
然后在onStateChange
文件中实现apptest.js
函数,该函数将获取更新的对象。
在下面查看我的示例并打开控制台,如果电子邮件有效,您将看到控制台日志中的错误和“ isValid”响应。