【问题标题】:ReactJs, Generating events outside of reactjs appReactJs,在 reactjs 应用程序之外生成事件
【发布时间】:2015-07-11 08:00:35
【问题描述】:

在尝试 ReactJs 时,我面临以下设计问题:

下面是一个简单的 html,我试图在其中模拟一个聊天应用程序,我目前正在构建一个在线成员列表并尝试编写代码以将新成员添加到列表中。

下面的 React 应用程序在其 DOM 层次结构中包含以下类。

ChatApp > 会员列表 > 会员

在 react 类 ChatApp 中,我可以使用 setInterval 更新成员集合并为新成员生成新 DOM,但现在我想从 ChatApp 类之外尝试相同的操作。

所以我添加了一个“添加成员”按钮,并希望在单击时调用一个函数,该函数又会向列表中添加一个新成员。

但是,我应该如何从 react 应用程序外部获取 react ChatApp 及其 setState 方法的实例?

<html>

<head>

    <style>
        .onlineList{
            width:300px;
            height:500px;
            display:inline-block;
            overflow:auto;
            border:1px solid lightgray;
        }

        .onlineList a{
            display:inline-block;
            width:100%;
            padding:10px;
            box-sizing:border-box;
            text-decoration:none;
            color:gray;
            font-weight:bold;
            border-top:1px solid lightgray;
            border-bottom:1px solid lightgray;
        }
        .onlineList a:hover{
            color:black;
            background-color:lightgray;
        }

    </style>

    <script src="js/jquery-1.11.3.min.js"></script>
    <script src="js/react-with-addons.js"></script>
    <script src="js/JSXTransformer.js"></script>

    <script>
        function addNewMember(){
            // How can the setState in chatApp react class be called from here?
        }
    </script>

    </head>

<body>
    <button onClick="addNewMember()">Add New Member</button>
    <div id="chatApp"></div>
    <script type="text/jsx">
        var Member = React.createClass({
            render: function() {
                return <a href='#'>{this.props.memberInfo}</a>;
            }
        });

        var MemberList = React.createClass({
            render: function(){
                var membersDOM = [];
                for(var m=0; m < this.props.members.length;m++){
                    membersDOM.push(<Member memberInfo={this.props.members[m].name}/>);
                }
                return (
                    <div id='onlineList' className={'onlineList'}>{membersDOM}</div>
                )
            }
        });

        var ChatApp = React.createClass({
            getInitialState: function(){
                var members = {
                    members: []
                };
                for(var m=0;m<1;m++){
                    members.members.push({name: m + 1});
                };

/*              setInterval(function(){
                    members.members.push({name: members.members.length + 1 });
                    this.setState(members);
                }.bind(this),2000);
*/
                return members;
            },
            render: function(){
                return (
                    <div id='container'>
                        <MemberList members={this.state.members}/>
                    </div>
                )
            }
        })

        React.render(
            <ChatApp/>,
            document.getElementById('chatApp')
        );

    </script>
</body>


</html>

【问题讨论】:

  • 如果您使用 React,您可能还应该使用 Flux 应用程序架构,它旨在与 React 的反应式渲染一起使用。查看facebook.github.io/flux/docs/overview.html。基本上,您将根据来自商店的数据来呈现您的组件。当 Add Member 被点击时,你发送一个 action 来更新 store,然后更新 react 组件。
  • @Hans,哦,好的,我去看看。

标签: javascript jquery reactjs


【解决方案1】:

您永远不应该在组件之外设置组件的状态。

应将 React 应用程序设置为组件的层次结构,顶级组件管理其子级的状态。因此,如果您希望在ChatApp 之外使用此功能,则需要将按钮连同您要修改的状态和addNewMember 处理程序一起移动到父组件中。然后您将该状态作为props 传递给ChatApp,就像您目前对MemberList 所做的那样。

话虽如此,您没有理由不能只在ChatApp 中包含按钮和addNewMember

addNewMember: function (e) {
  e.preventDefault();

  var name = this.state.members.length + 1;
  var members = this.state.members;

  this.setState({
    members: members.concat([{name: name}])
  });
}, 

render: function(){ 
  return (
    <div>
      <button onClick={this.addNewMember}>Add New Member</button>
      <div id='container'>
        <MemberList members={this.state.members}/>
      </div>
    </div>
  ) 
}

另外,这与您的问题没有直接关系,但您不应在getInitialState 中致电setState。它的目的是简单地实例化组件的状态,因为它在组件被渲染之前被调用一次,并且不会像其他生命周期方法那样触发重新渲染。

因此,在您的示例中,您将只返回一个空的 members 数组。然后,如果您想用setIntervalsetTimeout 或任何异步进程添加members,您可以在componentDidMount 中执行此操作。从上面使用addNewMember,它看起来像这样(如果你运行它,请确保考虑e):

getInitialState: function () {
  return {
    members: []
  };
},

componentDidMount: function () {
  setInterval(this.addNewMember, 2000);
}

无论如何,我希望这会有所帮助。有问题尽管问我。我很乐意详细介绍如何构建更复杂的 React 应用程序和最佳实践。

【讨论】:

  • 谢谢您的详细解释。我想尝试应用程序外部的“添加”按钮,因为我假设已经开发的页面具有一些用 jquery 编写的动态部分,该部分会根据页面中其他位置生成的事件/数据进行更新。现在,如果该部分被替换为反应组件并且对事件/数据生成机制没有/很少更改,那么整个事情将如何工作。这实际上可能不实用,但我只是想知道。
  • @codin 我不确定我是否理解您的要求。请提供更多详细信息...
  • 别管这个问题,我相信我现在应该专注于理解更好的反应。谢谢!
  • @codin 查看 Pete Hunt 在 React 上的视频。当我刚开始时,它真的帮助了我:youtu.be/DgVS-zXgMTk
猜你喜欢
  • 2019-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-27
  • 2022-01-03
  • 1970-01-01
  • 2016-10-12
相关资源
最近更新 更多