Code Monkey home page Code Monkey logo

flux-react-router-example's Introduction

Flux React Router Example

This is a sample Flux app I wrote on a weekend.
It uses open Github API to display starred repos by users and stargazers by repo.

Note: I now prefer Redux to Flux.
This example was ported to Redux.

I made it to document a few approaches I have tried while learning Flux.
I tried to keep it close to real world (pagination, no fake localStorage APIs).

There are a few bits here I was especially interested in:

Running

npm install
npm start

Doing Other Things

npm run lint # uses eslint
npm run build # build production version to dist folder

How I Classify Stores

I tried to avoid some of the duplication I've seen in other Flux example, specifically in Stores. I found it useful to logically divide Stores into three categories:

Content Stores hold all app entities. Everything that has an ID needs its own Content Store. Components that render individual items ask Content Stores for the fresh data.

Content Stores harvest their objects from all server actions. For example, UserStore looks into action.response.entities.users if it exists regardless of which action fired. There is no need for a switch. Normalizr makes it easy to flatten any API reponses to this format.

// Content Stores keep their data like this
{
  7: {
    id: 7,
    name: 'Dan'
  },
  ...
}

List Stores keep track of IDs of entities that appear in some global list (e.g. “feed”, “your notifications”). In this project, I don't have such Stores, but I thought I'd mention them anyway. They handle pagination.

They normally respond to just a few actions (e.g. REQUEST_FEED, REQUEST_FEED_SUCCESS, REQUEST_FEED_ERROR).

// Paginated Stores keep their data like this
[7, 10, 5, ...]

Indexed List Stores are like List Stores but they define one-to-many relationship. For example, “user's subscribers”, “repository's stargazers”, “user's repositories”. They also handle pagination.

They also normally respond to just a few actions (e.g. REQUEST_USER_REPOS, REQUEST_USER_REPOS_SUCCESS, REQUEST_USER_REPOS_ERROR).

In most social apps, you'll have lots of these and you want to be able to quickly create one more of them.

// Indexed Paginated Stores keep their data like this
{
  2: [7, 10, 5, ...],
  6: [7, 1, 2, ...],
  ...
}

See and run the source for more tips!

flux-react-router-example's People

Contributors

emmenko avatar gaearon avatar knowbody avatar kompot avatar neverov avatar yanandcoffee avatar zachasme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flux-react-router-example's Issues

Example of a programmatic transition as a reaction to an event

I would like to handle a situation when user creates an entity on a separate route and when operation is complete redirect him to the list of entities on a different route.

The flow is something like this:

  1. User clicks something like 'save stuff'
  2. An action is invoked and starts an async operation (ex. $.get('/stuff'))
  3. When operation finishes, store gets updated by dispatcher and emits a change event
  4. I need to make a transition via router with smth like router.transitionTo('whatever')

Maybe you can point me in the right direction how to handle this?

Delete a content store?

Hi, I have a question.

When content store belongs to a list store or indexed list store. How should I implements when delete that store?

Thank you

Object is not a hash

An object is not a hash.

Currently example fails with usernames such as constructor.

We solve this partially with 487745f but the same needs to be done for RepoStore and UserStore. The easiest way to do this is to create a Bag class and use it instead of mergeIntoBag, isInBag helpers. Inside Bag, we will use prefixes for IDs.

npm start does not work

I tried npm start and got this error

ERROR in ./scripts/components/Explore.js
Module not found: Error: Cannot resolve module 'react-router/transitionTo' in /Users/janmarek/www/flux-react-router-example/scripts/components
 @ ./scripts/components/Explore.js 11:19-55

ERROR in ./scripts/components/Repo.js
Module not found: Error: Cannot resolve module 'react-router/Link' in /Users/janmarek/www/flux-react-router-example/scripts/components
 @ ./scripts/components/Repo.js 14:11-39
webpack: bundle is now VALID.

Where do you clear stores?

Looking at your code I was wondering where is the point where you clear the store status.
I'll trying to explain myself.

When you are in the first page you submit the form, then in the UserPage you call

UserActionCreators.requestUser(userLogin, ['name', 'avatarUrl']);

At this point you will get the UserStore populated.

When you click back button and submit the form with another username, you start over the same process.

I was expecting here to see the UserStore still populated with previous data, but if I console.log {user} in UserPage render method, I see it is initially undefined, then populated again with the new user.

Since Stores are singleton, where do you reset it to undefined.
Probably you don't do it, maybe I see it undefined because is not in bag yet. but I'm missing something here.

Thanks

upgrade with React 0.14.3

Hello Guys,

I have tried to use this example using react-router with react 0.14.3 but failed because of peer dependency can you please upgrade with react 0.14.3

componentDidMount vs. componentWillMount

Hey,

Thanks for creating an actual flux application which actually does something real with AJAX, the official documentation in this area is lacking in the extreme.

The docs specify that AJAX requests should be conducted in componentDidMount, not in componentWillMount. I'm curious why you've done it there instead?

All the flux examples I've seen have the subscription happening in componentWillMount.

I saw issue #23, but it didn't really make it clear to me why the switch was made. It looked to me like the double rendering was being caused by the component rendering with whatever blank initial state was specified and then rendered again as soon as the server responded with the real content, which updated the store, which caused it to rerender? That's a pattern I've seen a lot with React with and without Flux in my limited exposure so far, it seems perfectly normal.

Thanks for your time.

Error with command: npm start

PS C:\Users\p-c\Downloads\Github\flux-react-router-example> npm start

[email protected] start
node server.js

C:\Users\p-c\Downloads\Github\flux-react-router-example\webpack.config.js:18
new webpack.NoErrorsPlugin()
^

TypeError: webpack.NoErrorsPlugin is not a constructor
at Object. (C:\Users\p-c\Downloads\Github\flux-react-router-example\webpack.config.js:18:5)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object. (C:\Users\p-c\Downloads\Github\flux-react-router-example\server.js:4:14)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)

Didn't understand object initialization notation

Hey @gaearon , thanks for opensourcing this great example 👍

I was taking a look at it and then found a way of initializing objects that i havent seen before:

{ PropTypes } = React;

// and

var {
  request,
  normalizeRepoResponse,
  normalizeRepoArrayResponse
} = require('./APIUtils');

I understand what is going on but .. where is this comming from? It is an es6 feature?

Thanks in advance!

connectToStore executing render twice on mount intended?

I had a question regarding the connectToStore component. It is doing a this.setState on componentDidMount. This will cause the component to execute render twice when it gets mounted.

Was this intended? What was the reason for running the this.setState on componentDidMount when getInitialState already sets the state?

I'm genuinely curious to know if I'm missing some lifecycle knowledge in the React lifecycle.

Handle cache invalidation

Hi,

This is a complex problem to solve for a simple example but I guess it's worth exploring.

When the data of an user is already loaded, it will never be refreshed.
This is not a big deal for many apps but for example a mobile app may be running for a very long time and can't assume it always have fresh data.

How would you solve this problem?

Missing link in README.md

Good morning and happy new year!

Could you please check and update the link to Redux example in README.md? It is leading to a 404 error page of github.

Thanks!

Using production config

Is it possible for this app to use the production webpack config? Looks like server.js is only configured to work with a dev webpack config.

webpack loader problem

I keep getting

Module parse failed: You may need an appropriate loader to handle this file type.

| import React from 'react';
| import { createHistory, createHashHistory } from 'history';
| import Root from './Root';
 @ multi main

Update to React 0.12

I'd gladly take a PR updating project to React 0.12.
Shouldn't be hard to do: bump the deps and incorporate fixes similar to Flux chat app fixes.

List Store/Index List Store

When you're building these stores, do you create them from the ContentStore response, or are these created from separate API calls?

Handle server-side rendering

Great work on putting this together! Just one question: Do you have an idea on how you would integrate server-side rendering into your app?

Are you using the actions?

can mergeIntoBag function extend to merge two array?

If my response have some arrays in the entities, the first store init is ok, but when the store changed, bag[key] = transform(assign({}, bag[key], entities[key])); will convert the bag[key] which should be array to object;
Cause it is only a example, so just ask.

Deal with stores

Hi @gaearon

I take a close look on your example and some post from you on google groups but I have some question that maybe you can help me.

I have a social network, pretty like facebook, and my first approach was to have a store to each page, so I end up with SearchStore, FeedStore, FriendStore, etc... that keep duplicated data (like user{name, avatar, etc}) into each one.

Good side is that when I make a fresh search, I replace old data with new one that will remove users data that is not used anymore (server always will return necessary users).

But with your approach (Content Store) I will end up with 5k, 10k, 300k users data that is not used anymore, even if it is used, server will return fresh users data. Is this not a issue? How di you deal with this?

Debugging with Webstorm ?

I'm very new to Nodejs and webpack .. so this might be a silly feature request. Is it possible to have this project to run and debugged under Webstorm ?

What I'm missing to integrate react-router inside a flux application?

First of I would like to thank you for all what your are doing for the react ecosystem,

I'm trying lately to using the react-router (currently v1.0.0-beta3) within a flux application, since there is no reference for doing this yet, I tried to read the code here and get some techniques and best practices, but it seems that there is so much magic going on here (a lot of ES6/7, higher-order components, ...) that I had hard time to get unfortunately .

What I tried so far

I just tried to port eviltrout/emberreddit/ to react/flux/react-router and come with this code tarrsalah/reactreddit, nothing special really, I copied a lot from your techniques.

The main problem I faced is how to update the component attached to a dynamic route when I change the url (by clicking on a Link or manually), the only way to get the dynamic parameters is by hooking inside componentWillReceiveProps ( and accessing to nextProps.params), in my sample I should request data by firing an action that create a promise (using whatwg-fetch), when the promise fulfilled the store get updated and emit a change to the component, the problem is that when I access to the dynamic url, the action get fired, the promise fulfilled, the store emit a change event but nothing get rendered on the component!

  componentDidMount: function() {
    SubredditStore.addChangeListener(this.handleChange);
  },

  componentWillUnmount: function() {
    SubredditStore.removeChangeListener(this.handleChange);
  },

  componentWillReceiveProps: function(nextProps) {
    requestData(nextProps);
  },

  handleChange: function() {
    console.log('handleChange');
    this.setState(getState(this.props));
  },

duplicate requests

Hello, thanks for the great flux example.
I'm trying to understand reactjs and flux, and have a question: what happenes if we make 2 async actions? For example request user with login tadjik1 and then we repeat this request. How can we protect our application from this collisions?

Cannot execute the search

As soon as i hit the Go! button i see the following error

Uncaught TypeError: Cannot read property 'dispatch' of undefined  AppDispatcher.js:10

Here is the relevant line

class AppDispatcher extends Dispatcher {
  /**
   * Dispatches three actions for an async operation represented by promise.
   */
  dispatchAsync(promise, types, action = {}) {
    const { request, success, failure } = types;

    this.dispatch(request, action);   === > Error here
    promise.then(
      response => this.dispatch(success, { ...action, response }),
      error => this.dispatch(failure, { ...action, error })
    );
  }

Port to Redux

I intend to port this example to Redux.

I'm not doing that to promote my library, but because reusable store utilities (like pagination) are way easier to implement as pure functions. What I have right now in PaginatedStoreUtils is a mess, and will be much more sensible with Redux approach.

However, I understand that not everybody will be happy with this change, as Redux is not exactly Flux. I think it solves the same problems better than Flux, but that's my opinion and some may not share it.

Therefore I ask what you think:

  • Should I rename the repository to reflect that it's a Redux example now?
  • Should I keep the old vanilla Flux code in a branch?

To clarify again:

  • I intend to keep it minimal, just like the current repo, and handle the same cases: pagination, “load more”, spinners.
  • The “content stores” / “list stores” distinction will be even clearer with reusable reducers.
  • This is not an artificial effort to port for the sake of porting. The code will be clearer after porting to Redux, and the idioms currently used by the code will be more apparent and natural.

Thoughts?

{}

Hi. I have some stupid question for you.
Why you heed {} here

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.