ReactJs + reflusso // trigger viene eseguito su componenti nullo?

voti
0

Sto cercando di utilizzare il reflusso dentro la mia ReactJs app.

Sto avendo un problema in cui un componente l'ascolto di un archivio di dati è in esecuzione la richiamata su un'istanza del componente vuota al posto del componente effettivo che è stato istanziato.

Dopo aver chiamato l'azione toggleUserBar , l'archivio dati è chiamata ed esegue il grilletto. Nel componente barra laterale , il callback viene chiamata ma lo stato del componente è vuoto:

TypeError Uncaught: Impossibile leggere la proprietà 'sd' undefined

Qualche idea di cosa sto facendo male?

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} />
    );

  };

}

Il componente barra laterale è resa in un altro componente:

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

Se io chiamo manualmente sdref.state.sd.open = true , funziona bene.

È pubblicato 19/12/2015 alle 16:31
fonte dall'utente
In altre lingue...                            


2 risposte

voti
1

La thisparola chiave in JavaScript spesso si comporta in modo sorprendente. Hai trovato quello principale.

Quando si crea una funzione interna utilizzando la functionparola chiave, non ottiene la stessa thisvariabile come la funzione di inclusione. Quindi questo significa che, nel codice:

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

Ci sono diversi modi per risolvere questo. Dal momento che si sta utilizzando ES6, il più semplice è probabilmente quello di utilizzare una funzione freccia - freccia funzioni mantenere in modo esplicito il thisriferimento della loro funzione di inclusione. Si sarebbe simile a questa:

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

Se non si sta utilizzando ES6, si potrebbe ottenere lo stesso comportamento chiamando bindin quella funzione (che permette di specificare la thisvariabile, così come tutti i parametri ad esso):

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
};
Risposto il 19/12/2015 a 17:06
fonte dall'utente

voti
0

this.state.sd.setState ({open: true}); dovrebbe essere 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} />
    );

  };

}

Risposto il 19/12/2015 a 16:41
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more