【问题标题】:ReactJs + Reflux // trigger is executed on null component?ReactJs + Reflux // 触发器在 null 组件上执行?
【发布时间】:2016-03-26 04:23:28
【问题描述】:

我正在尝试在我的 ReactJs 应用程序中使用 Reflux。

我遇到了一个问题,即侦听数据存储的组件正在空组件实例上执行回调,而不是实例化的实际组件。

在调用操作 toggleUserBar 时,会调用数据存储区并执行触发器。在组件Sidebar中,调用了回调但组件状态为空:

未捕获的类型错误:无法读取未定义的属性“sd”

知道我做错了什么吗?

actions.tsx

var Reflux = require('reflux');
var RQ = {};

RQ.actions = Reflux.createActions([
    "toggleUserBar"
]);

window.RQ = RQ;

store.tsx

RQ.store = Reflux.createStore({
  listenables: [RQ.actions],
  init: function() {},
  onToggleUserBar: function() {
      this.trigger();
  }
});

sidebar.tsx

import * as React from "react";
import * as ReactDOM  from "react-dom";

const LeftNav = require('material-ui/lib/left-nav');
const Menu = require('material-ui/lib/menu/menu')

interface ISidebarProps extends React.Props<any> {

}

interface ISidebarState extends React.Props<any> {
    shown: Boolean;
    sd: any;
}

export class Sidebar extends React.Component<ISidebarProps, ISidebarState> {

  unsubscribe: any;

  constructor(props: ISidebarProps) {
      super(props);
      this.state = { shown: true, sd: null };
  };

  componentDidMount() {
    this.unsubscribe = RQ.store.listen(function() {
      this.state.sd.setState({ open: true });
    });
  };

  componentWillUnmount() {
      this.unsubscribe();
  };

  render() {

    let menuItems = [
      { route: 'get-started', text: 'Get Started' },
      { route: 'customization', text: 'Customization' },
      { route: 'components', text: 'Components' }
    ];

    return (
      <LeftNav ref={(c) => this.state.sd = c} docked={false} openRight={true} menuItems={menuItems} />
    );

  };

}

侧边栏组件在另一个组件中渲染:

<ComSidebar ref={(c) => sdref = c} />

如果我手动调用 sdref.state.sd.open = true,它就可以正常工作。

【问题讨论】:

    标签: javascript reactjs refluxjs


    【解决方案1】:

    JavaScript 中的this 关键字经常以令人惊讶的方式表现。你已经找到了主要的。

    当您使用function 关键字创建内部函数时,它不会获得与封闭函数相同的this 变量。这意味着,在您的代码中:

    componentDidMount() {
      // "this" out here is your component instance
      this.unsubscribe = RQ.store.listen(function() {
        // "this" in here is NOT the same - undefined, as you're seeing
        this.setState({ open: true });
      });
    };
    

    有几种方法可以解决此问题。由于您使用的是 ES6,因此最简单的方法可能是使用箭头函数 - 箭头函数明确保留其封闭函数的 this 引用。它看起来像这样:

    componentDidMount() {
      this.unsubscribe = RQ.store.listen(() => {
        // now it's the same "this"
        this.setState({ open: true });
      });
    };
    

    如果您没有使用 ES6,则可以通过在该函数上调用 bind 来获得相同的行为(它允许您指定 this 变量以及它的任何参数):

    componentDidMount() {
      this.unsubscribe = RQ.store.listen(function() {
        this.setState({ open: true });
      }.bind(this)); 
      // by calling bind, we are explicitly setting the "this" variable here
      // passing it from outer scope to inner scope
    };
    

    【讨论】:

      【解决方案2】:

      this.state.sd.setState({ open: true });应该是 this.setState({open: true})。

      export class Sidebar extends React.Component<ISidebarProps, ISidebarState> {
      
        unsubscribe: any;
      
        constructor(props: ISidebarProps) {
            super(props);
            this.state = { shown: true, sd: null };
            this.storeDidChange = this.storeDidChange.bind(this);
        };
      
        componentDidMount() {
          this.unsubscribe = RQ.store.listen(this.storeDidChange);
        };
      
        componentWillUnmount() {
            this.unsubscribe();
        };
      
        storeDidChange() {
          this.refs.leftnav.open = true;
        }
      
        render() {
      
          let menuItems = [
            { route: 'get-started', text: 'Get Started' },
            { route: 'customization', text: 'Customization' },
            { route: 'components', text: 'Components' }
          ];
      
          return (
            <LeftNav ref={leftnav} docked={false} openRight={true} menuItems={menuItems} />
          );
      
        };
      
      }

      【讨论】:

      • 不幸的是,我得到“this.setState 不是函数”。由于某种原因,看起来“this”为空......
      猜你喜欢
      • 2016-02-29
      • 2010-10-01
      • 2017-03-03
      • 2015-07-17
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      相关资源
      最近更新 更多