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

Posted

技术标签:

【中文标题】父组件中的 Reactjs 按钮,在子组件中提交 Redux 表单【英文标题】:Reactjs button in Parent component which submits Redux Form in Child Component 【发布时间】:2019-03-07 18:37:59 【问题描述】:

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

<CompD> 包含一个带有 onSubmit=onSubmit 的 Redux 表单,带有一堆输入和一个带有 type="submit" 的保存按钮

<CompD> 的 sn-p 当前带有按钮:

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;

我想将此按钮移至&lt;CompA&gt;,因此&lt;CompA&gt; 中的按钮的行为方式与&lt;CompD&gt; 中的按钮完全相同并提交表单。

&lt;CompA&gt; 的 sn-p 添加了一个新按钮:

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

如何在&lt;CompA 中传递handleSubmit(data) 函数中的表单数据 有什么想法可以做到这一点吗?

【问题讨论】:

您想获取 CompA 中的按钮并将表单保留在 CompD 中吗? 您的意思是点击&lt;CompA&gt; 中的按钮,然后以某种方式触发&lt;CompD&gt; 中的Form 的onSubmit 事件,对吧? @NguyễnThanhTú 是的,这是正确的 @IvanBurnaev 是的 【参考方案1】:

React 组件使用 props 相互通信。 Parent -&gt; Child 通过propsChild -&gt; 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>

【讨论】:

谢谢你的详细回答,我已经编辑了我的帖子以包含代码sn-ps,你能看看 你想把数据保存在&lt;CompD /&gt;吗? 我不确定,但我想将Form 保留在那里,这是否意味着数据也应该保留在那里? 谢谢会检查,如果它有区别,我正在使用 Redux 表单并将状态映射到道具【参考方案2】:

您可以将表单提交状态和逻辑从 &lt;CompD&gt; 提升到 &lt;CompA&gt;,并且可以使用 React Context 提供表单状态和处理程序深入到 &lt;CompD&gt;,例如:

    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>

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

【讨论】:

谢谢你的详细回答,我已经编辑了我的帖子以包含代码sn-ps,你能看看 您好,我已阅读您更新的 sn-ps。如果在 之间有 甚至更多层,您可以选择使用 React Context,如我在答案的代码示例中所示;或者如果没有那么多层,您可以将onSubmitonChange 等从 传递到 ,就像显示的其他答案一样。

以上是关于父组件中的 Reactjs 按钮,在子组件中提交 Redux 表单的主要内容,如果未能解决你的问题,请参考以下文章

更改子输入时不刷新Reactjs父状态

在 React 中使用父组件中的按钮提交表单

VueJS:在子组件中触发事件时在父组件中运行函数

React Insert功能-子组件问题

Reactjs 入门基础

Vue 道具没有在子组件中正确更新