父组件中的Reactjs按钮可在子组件中提交Redux表单

时间:2018-10-02 15:32:07

标签: javascript reactjs forms redux components

我有4个嵌套组件,<CompD>嵌套在<CompC>内,而<CompB>嵌套在<CompA>内。

<CompD>包含一个带有onSubmit={onSubmit}的Redux表单和一堆输入,以及一个带有type="submit"的Save按钮

当前带有按钮的<CompD>片段:

const propTypes = {
  firstName: PropTypes.string,
  secondName: PropTypes.string
};

const defaultTypes = {
  firstName = " ",
  secondName = " "
};

const PollForm = ({
  firstName,
  secondName
}) => (
  <Form onSubmit={onSubmit}>
    .
    .
    <button type="submit">
      'Save'
    </button>
  </Form>
);

PollForm.propTypes = propTypes;
PollForm.defaultProps = defaultProps;

export default PollForm;

我想将按钮移至<CompA>,所以<CompA>中的按钮的行为与<CompD>中的按钮完全相同,并提交表单。

添加了新按钮的<CompA>片段:

const propTypes = {
  onSubmit: PropTypes.func, ...
};

const defaultTypes = {
  onSubmit: () = {}, ...
};

class Config extends Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this); ...
  }

  handleSubmit(data) {
    this.props.onSubmit(data);
  }

  render() {
    const {
    } = this.props;

    return (
      .
      .
      <button onClick={onSubmit}>
        'Save'
      </button>
    )
  }
}

如何在handleSubmit(data)中传递<CompA函数中来自表单的数据 有什么想法可以做到吗?

2 个答案:

答案 0 :(得分:1)

反应组件使用道具相互通信。 Parent -> Child经过propsChild -> Parent经过callback props。另一种方法是使用新的Context API。如果您有一个非常深的嵌套结构,那会更好。

下一个我展示了如何通过道具来完成。

class CompB extends React.Component {
  state = {
    name: "John Doe",
    email: "john@doe.com"
  }
  
  handleChange = e => {
    const {name, value} = e.target;       
    this.setState({[name]: value})
  }
  
  handleSubmit = e => {
    e.preventDefault();
   
    this.submit(this.state)
  }
  
  submit = (data) => {
    console.log("submitted", data, +new Date());
    
    this.props.onSubmit(data);
  }
  
  componentDidUpdate (oldProps) {
    if (!oldProps.shouldSubmit && this.props.shouldSubmit){
      this.submit(this.state);
    }
  }
  
  render () {
    const { name, email } = this.state; 
 
    return (
      <form onChange={this.handleChange} onSubmit={this.handleSubmit}>
        <div>
          <label>
            Name
            <input name="name" type="text" value={name} />
          </label>
        </div>

        <div>
          <label>
            Email
            <input name="email" type="email" value={email} />
          </label>
        </div>
      </form>
    )    
  }
}

class CompA extends React.Component { 
  state = {
    shouldSubmit: false,
  }
  
  submit = () => {
    this.setState({shouldSubmit: true})
  }
  
  handleSubmit = () => {
    this.setState({shouldSubmit: false})
  }
  
  render () {
    const {shouldSubmit} = this.state;
    
    return (
      <div>      
        <CompB 
          shouldSubmit={shouldSubmit} 
          onSubmit={this.handleSubmit}
        />
        
        <button 
          type="button" 
          onClick={this.submit}
        >
          Submit
        </button>
      </div>
    )
  }
}


ReactDOM.render(<CompA />, document.querySelector("#root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

答案 1 :(得分:1)

您可以将表单提交状态和逻辑从<CompD>提升到<CompA>,并且可以使用React Context提供深入到<CompD>的表单状态和处理程序,像这样:

    import React from 'react';
    import ReactDOM from 'react-dom';

    const FormContext = React.createContext();

    function CompB({ children }) {
      return <div id="B">{children}</div>;
    }
    function CompC({ children }) {
      return <div id="C">{children}</div>;
    }

    function CompD() {
      return (
        <FormContext.Consumer>
          {({ onSubmit, onChange, name }) => {
            return (
              <form onSubmit={onSubmit}>
                <label>
                  Name:
                  <input type="text" value={name} onChange={onChange} />
                </label>
                <input type="submit" value="submit-input" />
              </form>
            );
          }}
        </FormContext.Consumer>
      );
    }

    class CompA extends React.Component {
      onChange = ({ target: { value } }) => {
        this.setState({ name: value });
      };
      onSubmit = event => {
        event.preventDefault();
        console.log('Submitting name: ', this.state.name);
      };
      state = {
        name: 'defaultName',
        onSubmit: this.onSubmit,
        onChange: this.onChange,
      };
      render() {
        return (
          <FormContext.Provider value={this.state}>
            <CompB>
              <CompC>
                <CompD />
              </CompC>
            </CompB>
            <button name="submit" onClick={this.onSubmit}>submit-btn<button/>
          </FormContext.Provider>
        );
      }
    }

    ReactDOM.render(
        <CompA />,
        document.getElementById('root'),
      );
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>React App</title>
</head>

<body>
  <div id="root"></div>
  
</body>

</html>

但是将表单与“提交”按钮分开看起来确实很冗长。不知道为什么会有这样的需求,但是通常最好将它们组合在一个组件中。