【问题标题】:How to make a react component that can be controled from outside?如何制作一个可以从外部控制的反应组件?
【发布时间】:2017-06-21 16:07:08
【问题描述】:

我正在尝试使用 React 和 Material-UI 制作一个 Dialog 组件。

现在,我有 Material-UI 对话框的传统行为,在类中带有一个可以打开对话框的按钮。但我希望这个组件的行为与 Material-UI 对话框的行为相同。

所以我想改变他的状态并重新渲染调用它的组件,如下所示:

var open = false;
<AuthDialog open={open} />

并使用外部按钮将 open 变量更改为 true。

这是我的代码:

class AuthDialog extends React.Component {
    constructor(props, context){
        super(props, context);

        this.state = {
           open: false,
        };
    };

    handleRequestOpen = () => {
        this.setState({
            open: true,
        });
    };

    handleRequestClose = () => {
        this.setState({
            open: false,
        });
    };

    render() {
        return (
        <div>
            <RaisedButton children="login" onTouchTap={ this.handleRequestOpen } />
            <Dialog open={this.state.open} onRequestClose={this.handleRequestClose}>
                // Content
            </Dialog>
        </div>
        );
    }
}

我是 JS 的初学者,所以如果我的代码不正确,我也会感谢一些 cmets。

编辑:这是我修改后的代码:

class AuthDialog extends React.Component {
    constructor(props, context){
        super(props, context);

        this.state = {
            // State of authBody
        };  
    };

    render() {
        const { onRequestClose, open } = this.props;

        return (
            <Dialog open={open} onRequestClose={onRequestClose}>
                // Body of the dialog
            </Dialog>
        );
    }
}

在父级中:

closeAuthDialog = () => {
    this.setState({
        openAuthDialog: false,
    });
}

openAuthDialog = () => {
    this.setState({
        openAuthDialog: true,
    });
}

<RaisedButton children="login" onTouchTap={ this.openAuthDialog } />
<AuthDialog open={this.state.openAuthDialog} onRequestClose={this.closeAuthDialog} handleLoginSuccess={ this.handleLoginSuccess } />

【问题讨论】:

    标签: javascript reactjs material-ui


    【解决方案1】:

    为了实现这一点,您需要使用props 而不是本地状态。

    class AuthDialog extends React.PureComponent {
        static propTypes = {
          open: React.PropTypes.bool.isRequired,
          onClose: React.PropTypes.func.isRequired,
          onOpen: React.PropTypes.func.isRequired,
        };
    
        render() {
          const { onClose, onOpen, open } = this.props;
    
          return (
            <div>
                <RaisedButton children="login" onTouchTap={onOpen} />
                <Dialog open={open} onRequestClose={onClose}>
                    // Content
                </Dialog>
            </div>
          );
        }
    }
    

    然后你需要从父类发送两个函数和open prop。

    <AuthDialog open={open} onOpen={this.toggleOpenToTrue} onClose={this.toggleOpenToFalse} />
    

    【讨论】:

    • 谢谢,这正是我需要的。但最后我没有使用 propTypes,我只是做了@Yuriy Yakym 发布的内容。似乎 propTypes 已被弃用,我不想添加太多库。
    • 很高兴您使用了@Yuriy Yakym 提议的无状态组件,但即便如此,您也应该为该组件定义属性类型。不推荐从import React, { PropTypes } from 'react' 获取 PropTypes 对象,因为有一个新的通用包称为 prop-types -> import PropTypes from 'prop-types',您绝对应该在无状态组件上定义 propTypes
    【解决方案2】:

    只需像这样获取您从this.props 传递的属性:

    ...
    render() {
        const { open, onRaisedButtonClick } = this.props;
        return (
            <div>
                <RaisedButton children="login" onTouchTap={ onRaisedButtonClick } />
                <Dialog open={open} onRequestClose={this.handleRequestClose}>
                    // Content
                </Dialog>
            </div>
        );
    }
    ...
    

    另外,当你有没有生命周期方法的无状态组件时,你可以使用函数式组件;它更简单易读:

    const AuthDialog = ({ open, onRaisedButtonClick }) => (
        <RaisedButton children="login" onTouchTap={ onRaisedButtonClick } />
        <Dialog open={open} onRequestClose={this.handleRequestClose}>
            // Content
        </Dialog>
    )
    

    【讨论】:

      【解决方案3】:

      我不确定您到底在寻找什么。但据我了解,您想像这样使用 AuthDialog 组件;

      <AuthDialog open={open} />
      

      当点击&lt;RaisedButton/&gt; 时,您需要显示&lt;Dialog /&gt; 并且还需要更改父级上的'open' 状态/var。

      在这种情况下,您会想要使用 Flux 或 Redux 来管理您的应用状态。由于 React 中的双向绑定是一种不好的做法,这将是您实现这一目标的最佳方式。

      【讨论】:

      • 感谢您的回答,我不需要双向绑定(暂时不需要)。我只是想将所有控件传递给外部并删除 AuthDialog 中的按钮。感谢 Crysfel 和 Yuriy 的帖子,我实现了这一目标。
      • 太棒了,天哪!
      猜你喜欢
      • 2019-09-22
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 1970-01-01
      • 2015-02-21
      • 1970-01-01
      • 2013-01-31
      • 2018-10-25
      相关资源
      最近更新 更多