【问题标题】:How to pass props to one React Class to Another React Class?如何将道具传递给一个 React 类到另一个 React 类?
【发布时间】:2019-12-05 22:39:03
【问题描述】:

当在输入字段中输入文本时,我试图在模式中启用一个按钮。但是我的表单是在另一个类中构建的,并且在父类中使用。如何将onChange 方法传递给我的表单组件。

这是我的父组件:

import React from 'react';
import {
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle
} from '@material-ui/core';
import CompanyFinancialModalForm from '../CompanyFinancialModalForm/CompanyFinancialModalForm';

interface CompanyFinancialModalState {
  addEnabled: boolean;
}

interface CompanyFinancialModalProps {
  open: boolean;
  onClose: () => void;
}

export class CompanyFinancialModal extends React.Component<
  CompanyFinancialModalProps,
  CompanyFinancialModalState
> {
  constructor(props: CompanyFinancialModalProps) {
    super(props);

    this.state = {
      addEnabled: false
    };
  }

  private enableButton = () => {
    this.setState({ addEnabled: true});
  }

  public render() {
    const { open, onClose } = this.props;
    const { addEnabled } = this.state;
    return (
      <>
        <Dialog
          open={open}
          onClose={onClose}
          className="company-financial-modal"
        >
          <DialogTitle id="company-financial-modal-title">
            {'Company and Financial Data'}
          </DialogTitle>
          <DialogContent>
            <CompanyFinancialModalForm onChange={this.enableButton}/>
          </DialogContent>
          <DialogActions>
            <Button
              id="company-financial-modal-add"
              disabled={!addEnabled}
              onClick={onClose}
              color="primary"
            >
              Add
            </Button>
            <Button
              id="company-financial-modal-cancel"
              onClick={onClose}
              color="secondary"
              autoFocus={true}
            >
              Cancel
            </Button>
          </DialogActions>
        </Dialog>
      </>
    );
  }
}

export default CompanyFinancialModal;

这是我的表格所在的班级:

import React from 'react';
import axios from 'axios';
import { Form, Field } from 'react-final-form';
import { TextField, Select } from 'final-form-material-ui';
import {
  Paper,
  Grid,
  MenuItem,
} from '@material-ui/core';

export interface IValues {
  company_name: string;
  critical_technology: [];
}
export interface IFormState {
  [key: string]: any;
  values: IValues[];
  submitSuccess: boolean;
}

export default class CompanyFinancialModalForm extends React.Component<{}, IFormState> {
  constructor(props: {}) {
    super(props);
    this.state = {
      company_name: '',
      critical_technology: [],
      values: [],
      submitSuccess: false
    };
  }

  private processFormSubmission = (e: React.FormEvent<HTMLFormElement>): void => {
    e.preventDefault();
    this.setState({ loading: true });
    const formData = {
      company_name: this.state.company_name,
      critical_technology: this.state.critical_technology
    };
    this.setState({
      submitSuccess: true,
      values: [...this.state.values, formData],
      loading: false
    });
    axios.post(`http://localhost:8081/companies`, formData);
  }

  private onChange = (e: React.FormEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    // other form-related logic
    this.props.onChange({ name, value }, e);
  }

  public render() {
    const { submitSuccess, loading } = this.state;
    const { onChange } = this.props;
    return (
      <div>
        <Form
          onSubmit={this.processFormSubmission}
          // validate={this.validateForm}
          render={({ handleSubmit,/*  reset,  submitting, pristine, values*/ }) => (
          <form onSubmit={handleSubmit} noValidate>
            <Paper style={{ padding: 16 }}>
              <Grid container alignItems="flex-start" spacing={2}>
                <Grid item xs={6}>
                  <Field
                    fullWidth
                    required
                    name="companyName"
                    component={TextField}
                    type="text"
                    label="Company Name"
                    onChange={onChange}
                  />
                </Grid>                
                <Grid item xs={12}>
                  <Field
                    name="critical_technology"
                    label="Critical Technology"
                    component={Select as any}
                  >
                    <MenuItem value="hypersonics">Hypersonics</MenuItem>
                    <MenuItem value="directed_energy">Directed Energy</MenuItem>
                    <MenuItem value="command_control_and_communications">Command, Control and Communications </MenuItem>
                    <MenuItem value="space_offense_and_defense">Space Offense and Defense</MenuItem>
                    <MenuItem value="cybersecurity">Cybersecurity</MenuItem>
                    <MenuItem value="artificial_intelligence_machine_learning">Artificial Intelligence/Machine Learning</MenuItem>
                    <MenuItem value="missile_defense">Missile Defense</MenuItem>
                    <MenuItem value="quantum_science_and_computing">Quantum Science and Computing </MenuItem>
                    <MenuItem value="microelectronics">Microelectronics</MenuItem>
                    <MenuItem value="autonomy">Autonomy</MenuItem>
                  </Field>
                </Grid>
              </Grid>
            </Paper>
          </form>
        )}
      />
      </div>
    );
  }
}

我想将一个道具传递给&lt;CompanyFinancialModalForm /&gt;,当Textfield 输入文本时启用添加按钮。

【问题讨论】:

    标签: javascript reactjs material-ui react-final-form


    【解决方案1】:

    为了以后的参考,如果只包含相关代码会更有益,因为滚动浏览不相关的代码时需要更多时间来查找,无论如何:

    我不是 100% 清楚你在寻找什么,但我会尽量回答我认为我理解的内容。您可以在父组件上添加 onChange 方法,并将其作为道具传递给表单,并且表单可以在每次运行它自己的 onChange 方法时调用该函数。以下是简化版:

    class Parent extends Component {
      state = { 
        buttonEnabled: false,
        // formInputValue: '', <-- if you need this
      };
    
      // - omitting constructor/bind for simplicity for now
      onChange({ name, value }, e) {
        // your logic to determine whether button is enabled or not
        // this is just me guessing what you want to implement
        if (value) this.setState({ buttonEnabled: true });
        else this.setState({ buttonEnabled: false });
      }
    
      render() {
        return (
          <Fragment>
            <YourForm onChange={this.onChange} />
            <Button enabled={this.state.buttonEnabled} />
          </Fragment>
        );
      }
    }
    
    class YourForm extends Component {
      onChange(e) {
        const { name, value } = e.target;
        // other form-related logic
        this.props.onChange({ name, value }, e);
      }
    }
    

    这是你要找的吗?

    【讨论】:

    • 我正在寻找与我上面的代码更相关的东西
    • @AmenRa Stack Overflow 不是编码服务,您不能指望人们会为您浏览您的代码,告知问题所在,然后制作适合您的演示。以后请提供minimal-reproducible-example 以突出问题。
    【解决方案2】:

    您可以简单地向子级传递一个对父级中存在的函数的引用,然后使用父级的函数来验证和启用按钮。

    Codesandbox Demo

    简化代码:

    function Child (props) {
      return (
        <input type="text" onChange={props.doIt}/>
      )
    }
    
    function App() {
     const [disabled, setDisabled] = useState(true);
    
     function doIt(e) {
         setDisabled(e.currentTarget.value.length === 0);
     }
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <Child doIt={doIt} />
          <button disabled={disabled}>Add</button>
        </div>
      );
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-14
      • 2016-11-30
      • 2017-04-01
      • 2018-02-07
      • 1970-01-01
      • 2017-01-25
      • 2020-04-25
      • 2018-07-03
      • 1970-01-01
      相关资源
      最近更新 更多