Attila Kling
Attila Kling

Reputation: 1787

Communication between Components

Here's my situation, I'm very new to react/flux, and just started to play around with it. My toy project is a simple library app. My current state is as follows:

I'm struggling to find out how to re-render my library component if i change the current user. Since its my first project, I don't want to play around with proper authentication, or create a router. So I simply made a Login form and whenever the user input's his name, and logs in, i render the library app onto the DOM.

Login = React.createClass({

  _handleSubmit: function () {

    var inp = this.refs.login.getDOMNode();

    sessionStorage.setItem("username", inp.value);
    console.info('User Credentials saved to SessionStorage');
    inp.value = '';

    React.renderComponent(
      <Library />,
      document.querySelector('#content')
    );
  },

  render: function () {
    return (
      <div className="panel panel-default">
        blabla
                  <button className="btn btn-default" type="button" onClick={this._handleSubmit} >
                    Login
                  </button>
        blabla
      </div>
    );
  }
});

This works well, but i think it's far from an optimal approach. Whenever i Login again, react is re-rendering a new instance from the Library component into the DOM node. I'm not dealing with destructuring at all, and I think it's bad :( I know react will not append, but erase and fill into the node, but the event handlers will possibly remain etc.

So what could be a possible good solution for my situation?

I have 3 possible solutions in my mind

  1. Either i should develop an event system to be able to notify the Library component if I re-login with a different user to re-render itself, or
  2. I could build up a parent-child relationship upon Login & Library, so when i modify the state of the Login component my Library app would re-render too.
  3. Call an Action which would update the component
  4. Stick with current

:) Thanks for any answer, Cheers

Hint:

app.js

'use strict';
var React = require('react'),
    Login = require('./components/Login.jsx');

// Dev-tools
window.React = React;

React.renderComponent(
  Login(),
  document.querySelector('#login')
);

Login.jsx

mentioned upper

Library.jsx

/** @jsx React.DOM */
'use strict';
var React = require('react'),
    BookShelf = require('./BookShelf.jsx'),
    Store = require('../stores/Store'),
    Library;

/**
 * Gets state from Storage
 * @returns {{books: BookCollection, users: UserCollection, categories: CategoryCollection}}
 */
function getState() {
  var state = Store.getAll();
  return {
    books: state.books,
    users: state.users,
    categories: state.categories
  };
}

Library = React.createClass({
  getInitialState: function() {
    return getState();
  },
  componentDidMount: function() {
    Store.addChangeListener(this._onChange);
    Store.initialize();
  },
  componentWillUnmount: function() {
    Store.removeChangeListener(this._onChange);
  },
  _onChange: function() {
    this.setState(getState());
  },
  render: function() {
    return (
      <div>
        <BookShelf
          books={this.state.books}
          users={this.state.users}
          categories={this.state.categories}
        />
      </div>
    );
  }
});

module.exports = Library;

Upvotes: 1

Views: 2074

Answers (1)

fisherwebdev
fisherwebdev

Reputation: 12690

If this is a Flux app, then you want to take all that application logic and application state and move it into a store (or multiple stores).

Right now, it looks like you're doing that just fine for things related to the library. I would rename that store LibraryStore. But you probably want an AppStore or a UserStore or a SessionStore or something that has the logic and data related to the login state, current user, and auth token.

So then once the user logs in, yes you would want to create an Action (option #3) to let all the different stores in you app know that your user has logged in, but primarily to inform the AppStore. Then your top-level controller-views can listen to AppStore and decide what to display. If you're using React's event model, you don't need to worry about cleaning up the event handlers. Flux controller-views don't use the React model, so we have to cleanup those on unmounting.

Part of your difficulty may be coming from simulating processes that are async. Authentication, for example, will require a server call, and your new action would be created in the success/error callback to that call. To simulate this against localStorage, you might make a sync query of the storage and then call one of two different actions for success/failure.

Upvotes: 5

Related Questions