You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:00:47