Material UI 1.0中如何实现按钮满足条件后触发页面导航?
如何实现Material UI按钮满足条件后才触发页面导航?
当然可以实现!针对你使用的Material UI 1.0.0-beta.41和react-router-dom场景,这里有两种实用的解决方案:
方案一:手动控制点击事件与路由跳转
这是最直接的方式——放弃直接将Link传给Button的component属性,转而手动处理按钮的点击事件,先完成表单验证,通过后再触发路由跳转。
函数组件示例(使用useHistory钩子)
import { useHistory } from 'react-router-dom'; import Button from 'material-ui/Button'; import { useState } from 'react'; function ValidatedForm() { const history = useHistory(); // 存储表单数据和验证错误信息 const [formData, setFormData] = useState({ username: '', email: '' }); const [validationErrors, setValidationErrors] = useState({}); // 表单验证逻辑 const validateForm = () => { const errors = {}; if (!formData.username.trim()) { errors.username = '用户名不能为空'; } if (!formData.email.includes('@')) { errors.email = '请输入有效的邮箱地址'; } setValidationErrors(errors); // 验证通过返回true,否则false return Object.keys(errors).length === 0; }; // 按钮点击处理函数 const handleNavigate = () => { const isFormValid = validateForm(); if (isFormValid) { // 验证通过,跳转到目标页面 history.push('/open-collective'); } }; return ( <div> {/* 表单输入区域 */} <div> <label>用户名:</label> <input type="text" value={formData.username} onChange={(e) => setFormData({ ...formData, username: e.target.value })} /> {validationErrors.username && <span style={{ color: 'red' }}>{validationErrors.username}</span>} </div> <div> <label>邮箱:</label> <input type="email" value={formData.email} onChange={(e) => setFormData({ ...formData, email: e.target.value })} /> {validationErrors.email && <span style={{ color: 'red' }}>{validationErrors.email}</span>} </div> {/* 带验证的跳转按钮 */} <Button onClick={handleNavigate} variant="contained" color="primary"> 确认跳转 </Button> </div> ); }
类组件示例(使用withRouter高阶组件)
如果你的项目还在使用类组件,可以用withRouter包裹组件来获取history对象:
import { withRouter } from 'react-router-dom'; import Button from 'material-ui/Button'; import React, { Component } from 'react'; class ValidatedForm extends Component { state = { formData: { username: '', email: '' }, validationErrors: {} }; validateForm = () => { const { formData } = this.state; const errors = {}; if (!formData.username.trim()) { errors.username = '用户名不能为空'; } if (!formData.email.includes('@')) { errors.email = '请输入有效的邮箱地址'; } this.setState({ validationErrors: errors }); return Object.keys(errors).length === 0; }; handleNavigate = () => { const isFormValid = this.validateForm(); if (isFormValid) { this.props.history.push('/open-collective'); } }; render() { const { formData, validationErrors } = this.state; return ( <div> {/* 表单输入区域省略,逻辑与函数组件一致 */} <Button onClick={this.handleNavigate} variant="contained" color="primary"> 确认跳转 </Button> </div> ); } } // 用withRouter包裹组件,注入history属性 export default withRouter(ValidatedForm);
方案二:封装带验证的自定义Link组件
如果你想保留Button使用component属性的写法,可以封装一个带验证逻辑的自定义Link组件,将验证逻辑作为props传入:
import { Link } from 'react-router-dom'; import Button from 'material-ui/Button'; import { useState } from 'react'; // 自定义带验证的Link组件 const ValidatedLink = ({ to, validate, children, ...props }) => { const handleClick = (e) => { const isFormValid = validate(); if (!isFormValid) { // 验证不通过时,阻止Link的默认跳转行为 e.preventDefault(); } }; return ( <Link to={to} onClick={handleClick} {...props}> {children} </Link> ); }; // 在表单组件中使用 function ValidatedForm() { const [formData, setFormData] = useState({ username: '', email: '' }); const [validationErrors, setValidationErrors] = useState({}); const validateForm = () => { const errors = {}; if (!formData.username.trim()) { errors.username = '用户名不能为空'; } if (!formData.email.includes('@')) { errors.email = '请输入有效的邮箱地址'; } setValidationErrors(errors); return Object.keys(errors).length === 0; }; return ( <div> {/* 表单输入区域省略 */} <Button component={ValidatedLink} to="/open-collective" validate={validateForm} variant="contained" color="primary" > 确认跳转 </Button> </div> ); }
方案选择建议
- 如果只是单一页面的简单验证需求,方案一的手动控制方式更直观,代码量也更少;
- 如果多个页面都需要带验证的跳转按钮,方案二的自定义组件可以实现逻辑复用,减少重复代码。
内容的提问来源于stack exchange,提问作者Kayce Basques
相关产品推荐
相关产品推荐

