我正在构建一个表单--用户在进入下一个屏幕之前需要回答的一系列问题(单选按钮)。对于字段验证,我使用yup(npm包)和redux作为状态管理。
对于一个特定的场景/组合,将显示一个新屏幕(div),要求用户确认(复选框),然后才能继续。我希望仅在显示时对此复选框应用验证。
如何使用React检查DOM中是否显示了元素(div)?
我想到的方法是将变量“isScreenVisible”设置为false,如果满足条件,我将把状态更改为“true”。
我正在做这个检查,并在_renderScreen()中将'isScreenVisible'设置为true或false,但由于某种原因,它进入了一个无限循环。
我的代码:
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
formisValid: true,
errors: {},
isScreenVisible: false
}
this.FormValidator = new Validate();
this.FormValidator.setValidationSchema(this.getValidationSchema());
}
areThereErrors(errors) {
var key, er = false;
for(key in errors) {
if(errors[key]) {er = true}
}
return er;
}
getValidationSchema() {
return yup.object().shape({
TravelInsurance: yup.string().min(1).required("Please select an option"),
MobilePhoneInsurance: yup.string().min(1).required("Please select an option"),
Confirmation: yup.string().min(1).required("Please confirm"),
});
}
//values of form fields
getValidationObject() {
let openConfirmation = (this.props.store.Confirmation === true)? 'confirmed': ''
return {
TravelInsurance: this.props.store.TravelInsurance,
MobilePhoneInsurance: this.props.store.MobilePhoneInsurance,
Confirmation: openConfirmation,
}
}
setSubmitErrors(errors) {
this.setState({errors: errors});
}
submitForm() {
var isErrored, prom, scope = this, obj = this.getValidationObject();
prom = this.FormValidator.validateSubmit(obj);
prom.then((errors) => {
isErrored = this.FormValidator.isFormErrored();
scope.setState({errors: errors}, () => {
if (isErrored) {
} else {
this.context.router.push('/Confirm');
}
});
});
}
saveData(e) {
let data = {}
data[e.target.name] = e.target.value
this.props.addData(data)
this.props.addData({
Confirmation: e.target.checked
})
}
_renderScreen = () => {
const {
Confirmation
} = this.props.store
if(typeof(this.props.store.TravelInsurance) !== 'undefined' && typeof(this.props.store.MobilePhoneInsurance) !== 'undefined') &&
((this.props.store.TravelInsurance === 'Yes' && this.props.store.MobilePhoneInsurance === 'No') ||
(this.props.store.TravelInsurance === 'No' && this.props.store.MobilePhoneInsurance === 'Yes')){
this.setState({
isScreenVisible: true
})
return(
<div>
<p>Please confirm that you want to proceed</p>
<CheckboxField
id="Confirmation"
name="Confirmation"
value={Confirmation}
validationMessage={this.state.errors.Confirmation}
label="I confirm that I would like to continue"
defaultChecked={!!Confirmation}
onClick={(e)=> {this.saveData(e)} }
/>
</FormLabel>
</div>
)
}
else{
this.setState({
isScreenVisible: false
})
}
}
render(){
const {
TravelInsurance,
MobilePhoneInsurance
} = this.props.store
return (
<div>
<RadioButtonGroup
id="TravelInsurance"
name="TravelInsurance"
checked={TravelInsurance}
onClick={this.saveData.bind(this)}
options={{
'Yes': 'Yes',
'No': 'No'
}}
validationMessage={(this.state.errors.TravelInsurance) ? this.state.errors.TravelInsurance : null }
/>
<RadioButtonGroup
id="MobilePhoneInsurance"
name="MobilePhoneInsurance"
checked={MobilePhoneInsurance}
onClick={this.saveData.bind(this)}
options={{
'Yes': 'Yes',
'No': 'No'
}}
validationMessage={(this.state.errors.MobilePhoneInsurance) ? this.state.errors.MobilePhoneInsurance : null }
/>
this._renderScreen()
<ButtonRow
primaryProps={{
children: 'Continue',
onClick: e=>{
this.submitForm();
}
}}
</div>
)
}
}
const mapStateToProps = (state) => {
return {
store: state.Insurance,
}
}
const Insurance = connect(mapStateToProps,{addData})(Component)
export default Insurance
9条答案
按热度按时间mm5n2pyu1#
下面是一个利用IntersectionObserver API的可重用钩子。
钩子
用法
bis0qfac2#
您可以将一个ref附加到要检查其是否位于视口中的元素,然后显示如下内容:
您可以附加
onScroll
之类的侦听器,并检查元素何时出现在视口中。您也可以使用Intersection Observer API with a polyfil或使用HoC component that does the job
a8jjtwal3#
根据Avraam的回答,我编写了一个与Typescript兼容的小钩子来满足实际的React代码约定。
用法示例:
你可以找到example on Codesandbox。我希望你会发现它有帮助!
lhcgjxsq4#
@Alex Gusev在没有lodash的情况下使用useRef回答
用法示例:
eanckbw95#
我也遇到过同样的问题,而且,看起来,我在pure react jsx中找到了相当好的解决方案,没有安装任何库。
我试图弄清楚如何动画元素,如果在视口。
Here is work project on CodeSandbox.
v440hwme6#
这是基于
Creaforge
的答案,但对于您希望检查组件是否已变为可见(以及在TypeScript中)的情况,这一点更为优化。钩子
用法
请记住,如果在调用钩子的同时没有挂载组件,那么就必须使代码变得更加复杂。
ryoqjall7#
基于TypeScript的@Creaforge的Intersection Observer方法,修复了
ref.current
可能未定义的问题(如果在挂载元素之前调用挂钩):用法:
nukf8bse8#
答案基于@Alex Gusev的帖子
React挂接检查元素是否可见,并进行了一些修复并基于rxjs库。
balp4ylt9#
在使用TypeScript尝试了不同的建议解决方案后,我们一直面临着错误,这是由于第一次渲染将默认
useRef
设置为null
。这是我们的解决方案,以防万一它能帮助其他人😊
钩子
useInViewport.ts
:用法
SomeReactComponent.tsx
:感谢@isma-navarro提供的解决方案😊