如何将道具从一个React类传递到另一个React类?

时间:2019-12-05 22:39:03

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

我试图在输入字段中输入文本时在模式中启用按钮。但是我的表单是在另一个类中构建的,并在父类中使用。如何传递表单组件的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>
    );
  }
}

我想将一个道具传递给<CompanyFinancialModalForm />,以便在Textfield中键入文本时启用添加按钮。

2 个答案:

答案 0 :(得分:1)

为了以后的参考,如果仅包含相关代码,将会更加有益,因为无论如何,滚动无关代码时需要花费更多时间:

我不清楚您要寻找的是什么,但我会尽力回答我认为的理解。您可以在父组件上添加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);
  }
}

这是您要找的吗?

答案 1 :(得分:0)

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

this post

简化代码:

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>
  );
}