diff --git a/README.md b/README.md index 7dac4450..d100e07c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Flux An application architecture for React utilizing a unidirectional data flow. - + ## Getting Started diff --git a/docs/Dispatcher.ko-KR.md b/docs/Dispatcher.ko-KR.md index 7bc17c87..cc2addd3 100644 --- a/docs/Dispatcher.ko-KR.md +++ b/docs/Dispatcher.ko-KR.md @@ -1,11 +1,6 @@ --- id: dispatcher-ko-KR title: Dispatcher -layout: docs -category: Reference -permalink: docs/dispatcher-ko-KR.html -next: videos-ko-KR -lang: ko-KR --- Dispatcher는 등록된 callback에 데이터를 중계할 때 사용된다. 일반적인 pub-sub 시스템과는 다음 두 항목이 다르다: @@ -17,24 +12,24 @@ Dispatcher는 등록된 callback에 데이터를 중계할 때 사용된다. 일 ## API -- **register(function callback): string** -모든 데이터 변동이 있을 때 실행될 콜백을 등록한다. `waitFor()`에서 사용 가능한 토큰을 반환한다. +- **`register(function callback): string`** + 모든 데이터 변동이 있을 때 실행될 콜백을 등록한다. `waitFor()`에서 사용 가능한 토큰을 반환한다. -- **unregister(string id): void** -토큰으로 콜백을 제거한다. +- **`unregister(string id): void`** + 토큰으로 콜백을 제거한다. -- **waitFor(array ids): void** -현재 실행한 콜백이 진행되기 전에 특정 콜백을 지연하게 한다. 데이터 변동에 응답하는 콜백에만 사용해야 한다. +- **`waitFor(array ids): void`** + 현재 실행한 콜백이 진행되기 전에 특정 콜백을 지연하게 한다. 데이터 변동에 응답하는 콜백에만 사용해야 한다. -- **dispatch(object payload): void** 등록된 모든 콜백에 데이터를 전달한다. +- **`dispatch(object payload): void`** 등록된 모든 콜백에 데이터를 전달한다. -- **isDispatching(): boolean** 이 Dispatcher가 지금 데이터를 전달하고 있는지 확인한다. +- **`isDispatching(): boolean`** 이 Dispatcher가 지금 데이터를 전달하고 있는지 확인한다. ## 예시 가상의 비행 목적지 양식에서 국가를 선택했을 때 기본 도시를 선택하는 예를 보자: -``` +```js var flightDispatcher = new Dispatcher(); // 어떤 국가를 선택했는지 계속 추적한다 @@ -49,7 +44,7 @@ var FlightPriceStore = {price: null}; 사용자가 선택한 도시를 변경하면 데이터를 전달한다: -``` +```js flightDispatcher.dispatch({ actionType: 'city-update', selectedCity: 'paris' @@ -58,7 +53,7 @@ flightDispatcher.dispatch({ 이 데이터 변동은 `CityStore`가 소화한다: -``` +```js flightDispatcher.register(function(payload) { if (payload.actionType === 'city-update') { CityStore.city = payload.selectedCity; @@ -68,7 +63,7 @@ flightDispatcher.register(function(payload) { 사용자가 국가를 선택하면 데이터를 전달한다: -``` +```js flightDispatcher.dispatch({ actionType: 'country-update', selectedCountry: 'australia' @@ -77,17 +72,18 @@ flightDispatcher.dispatch({ 이 데이터는 두 store에 의해 소화된다: -``` +```js CountryStore.dispatchToken = flightDispatcher.register(function(payload) { if (payload.actionType === 'country-update') { CountryStore.country = payload.selectedCountry; } }); ``` + `CountryStore`가 등록한 콜백을 업데이트 할 때 반환되는 토큰을 참조값으로 저장했다. 이 토큰은 `waitFor()` 에서 사용할 수 있고 `CityStore`가 갱신하는 것보다 먼저 `CountryStore`를 갱신하도록 보장할 수 있다. -``` +```js CityStore.dispatchToken = flightDispatcher.register(function(payload) { if (payload.actionType === 'country-update') { // `CountryStore.country`는 업데이트 되지 않는다 @@ -102,7 +98,7 @@ CityStore.dispatchToken = flightDispatcher.register(function(payload) { `waitFor()`는 다음과 같이 묶을 수 있다: -``` +```js FlightPriceStore.dispatchToken = flightDispatcher.register(function(payload) { switch (payload.actionType) { diff --git a/docs/Dispatcher.md b/docs/Dispatcher.md index 71782d1e..bc17448f 100644 --- a/docs/Dispatcher.md +++ b/docs/Dispatcher.md @@ -1,43 +1,39 @@ --- id: dispatcher title: Dispatcher -layout: docs -category: Reference -permalink: docs/dispatcher.html -next: flux-utils --- Dispatcher is used to broadcast payloads to registered callbacks. This is different from generic pub-sub systems in two ways: - Callbacks are not subscribed to particular events. Every payload is - dispatched to every registered callback. + dispatched to every registered callback. - Callbacks can be deferred in whole or part until other callbacks have - been executed. + been executed. Check out [Dispatcher.js](https://github.com/facebook/flux/blob/master/src/Dispatcher.js) for the source code. ## API -- **register(function callback): string** -Registers a callback to be invoked with every dispatched payload. Returns a token that can be used with `waitFor()`. +- **`register(function callback): string`** + Registers a callback to be invoked with every dispatched payload. Returns a token that can be used with `waitFor()`. -- **unregister(string id): void** -Removes a callback based on its token. +- **`unregister(string id): void`** + Removes a callback based on its token. -- **waitFor(array ids): void** -Waits for the callbacks specified to be invoked before continuing execution of the current callback. This method should only be used by a callback in response to a dispatched payload. +- **`waitFor(array ids): void`** + Waits for the callbacks specified to be invoked before continuing execution of the current callback. This method should only be used by a callback in response to a dispatched payload. -- **dispatch(object payload): void** Dispatches a payload to all registered callbacks. +- **`dispatch(object payload): void`** Dispatches a payload to all registered callbacks. -- **isDispatching(): boolean** Is this Dispatcher currently dispatching. +- **`isDispatching(): boolean`** Is this Dispatcher currently dispatching. ## Example For example, consider this hypothetical flight destination form, which selects a default city when a country is selected: -``` +```js var flightDispatcher = new Dispatcher(); // Keeps track of which country is selected @@ -52,7 +48,7 @@ var FlightPriceStore = {price: null}; When a user changes the selected city, we dispatch the payload: -``` +```js flightDispatcher.dispatch({ actionType: 'city-update', selectedCity: 'paris' @@ -61,7 +57,7 @@ flightDispatcher.dispatch({ This payload is digested by `CityStore`: -``` +```js flightDispatcher.register(function(payload) { if (payload.actionType === 'city-update') { CityStore.city = payload.selectedCity; @@ -71,7 +67,7 @@ flightDispatcher.register(function(payload) { When the user selects a country, we dispatch the payload: -``` +```js flightDispatcher.dispatch({ actionType: 'country-update', selectedCountry: 'australia' @@ -80,7 +76,7 @@ flightDispatcher.dispatch({ This payload is digested by both stores: -``` +```js CountryStore.dispatchToken = flightDispatcher.register(function(payload) { if (payload.actionType === 'country-update') { CountryStore.country = payload.selectedCountry; @@ -93,7 +89,7 @@ to the returned token. Using this token with `waitFor()`, we can guarantee that `CountryStore` is updated before the callback that updates `CityStore` needs to query its data. -``` +```js CityStore.dispatchToken = flightDispatcher.register(function(payload) { if (payload.actionType === 'country-update') { // `CountryStore.country` may not be updated. @@ -108,7 +104,7 @@ CityStore.dispatchToken = flightDispatcher.register(function(payload) { The usage of `waitFor()` can be chained, for example: -``` +```js FlightPriceStore.dispatchToken = flightDispatcher.register(function(payload) { switch (payload.actionType) { diff --git a/docs/Flux-Utils.md b/docs/Flux-Utils.md index 1e9cf21a..27c31a61 100644 --- a/docs/Flux-Utils.md +++ b/docs/Flux-Utils.md @@ -1,10 +1,6 @@ --- id: flux-utils title: Flux Utils -layout: docs -category: Reference -permalink: docs/flux-utils.html -next: videos --- Flux Utils is a set of basic utility classes to help get you started with Flux. These base classes are a solid foundation for a simple Flux application, but they are **not** a feature-complete framework that will handle all use cases. There are many other great Flux frameworks out there if these utilities do not fulfill your needs. @@ -13,14 +9,14 @@ Flux Utils is a set of basic utility classes to help get you started with Flux. There are three main classes exposed in Flux Utils: -1. Store -2. ReduceStore -3. Container +1. `Store` +1. `ReduceStore` +1. `Container` These base classes can be imported from `flux/utils` like this: ```js -import {ReduceStore} from 'flux/utils'; +import { ReduceStore } from 'flux/utils'; class CounterStore extends ReduceStore { getInitialState(): number { @@ -48,81 +44,97 @@ There are some best practices we try to follow when using these classes: ### Stores -1. Cache data -2. Expose public getters to access data (never have public setters) -3. Respond to specific actions from the dispatcher -4. Always emit a change when their data changes -5. Only emit changes during a dispatch +- Cache data +- Expose public getters to access data (never have public setters) +- Respond to specific actions from the dispatcher +- Always emit a change when their data changes +- Only emit changes during a dispatch ### Actions -1. Describe a user's action, are not setters. (e.g. `select-page` not `set-page-id`) +Describe a user's action, are not setters. (e.g. `select-page` not `set-page-id`) ### Containers -1. Are react components that control a view -2. Primary job is to gather information from stores and save it in their state -3. Have no props and no UI logic +- Are React components that control a view +- Primary job is to gather information from stores and save it in their state +- Have no `props` and no UI logic ### Views -1. Are react components that are controlled by a container -2. Have all of the UI and rendering logic -3. Receive all information and callbacks as props +- Are React components that are controlled by a container +- Have all of the UI and rendering logic +- Receive all information and callbacks as props -# API +## API -## Store +### `Store` + +#### `constructor(dispatcher: Dispatcher)` -- **constructor(dispatcher: Dispatcher)** Constructs and registers an instance of this store with the given dispatcher. -- **addListener(callback: Function): {remove: Function}** +#### `addListener(callback: Function): {remove: Function}` + Adds a listener to the store, when the store changes the given callback will be called. A token is returned that can be used to remove the listener. Calling the `remove()` function on the returned token will remove the listener. -- **getDispatcher(): Dispatcher** +#### `getDispatcher(): Dispatcher` + Returns the dispatcher this store is registered with. -- **getDispatchToken(): DispatchToken** +#### `getDispatchToken(): DispatchToken` + Returns the dispatch token that the dispatcher recognizes this store by. Can be used to `waitFor()` this store. -- **hasChanged(): boolean** +#### `hasChanged(): boolean` + Ask if a store has changed during the current dispatch. Can only be invoked while dispatching. This can be used for constructing derived stores that depend on data from other stores. -- **__emitChange(): void** +#### `__emitChange(): void` + Emit an event notifying all listeners that this store has changed. This can only be invoked when dispatching. Changes are de-duplicated and resolved at the end of this store's `__onDispatch` function. -- **__onDispatch(payload: Object): void** +#### `onDispatch(payload: Object): void` + Subclasses must override this method. This is how the store receives actions from the dispatcher. All state mutation logic must be done during this method. -## ReduceStore +--- + +### `ReduceStore` -- **extends Store** -This class extends the base Store. +This class extends the base `Store`. + +#### `getState(): T` -- **getState(): T** Getter that exposes the entire state of this store. If your state is not immutable you should override this and not expose state directly. -- **getInitialState(): T** +#### `getInitialState(): T` + Constructs the initial state for this store. This is called once during construction of the store. -- **reduce(state: T, action: Object): T** +#### `reduce(state: T, action: Object): T` + Reduces the current state, and an action to the new state of this store. All subclasses must implement this method. This method should be pure and have no side-effects. -- **areEqual(one: T, two: T): boolean** +#### `areEqual(one: T, two: T): boolean` + Checks if two versions of state are the same. You do not need to override this if your state is immutable. -- **Doesn't need to emit a change** +#### Doesn't Need to Emit a Change + Note that any store that extends `ReduceStore` does not need to manually emit changes in `reduce()` (you still can if you want to though). The state is compared before and after each dispatch and changes are emitted automatically. If you need to control this behavior (perhaps because your state is mutable) override `areEqual()`. -## Container +--- + +### `Container` + +#### `create(base: ReactClass, options: ?Object): ReactClass` -- **create(base: ReactClass, options: ?Object): ReactClass** Create is used to transform a react class into a container that updates its state when relevant stores change. The provided base class must have static methods `getStores()` and `calculateState()`. ```js -import {Component} from 'react'; -import {Container} from 'flux/utils'; +import { Component } from 'react'; +import { Container } from 'flux/utils'; class CounterContainer extends Component { static getStores() { @@ -145,19 +157,17 @@ const container = Container.create(CounterContainer); Additional options may be provided when creating your container in order to control certain behaviors. -- **containers are pure** -By default containers are pure, meaning they will not re-render when their props and state do not change (as determined by `shallowEquals()`). To disable this behavior pass options `{pure: false}` as the second argument to `create()`. +- **Containers are pure** - By default containers are pure, meaning they will not re-render when their props and state do not change (as determined by `shallowEquals()`). To disable this behavior pass options `{pure: false}` as the second argument to `create()`. -- **containers cannot access props** -By default containers are not able to access any props. This is both for performance reasons, and to ensure that containers are re-usable and props do not have to be threaded throughout a component tree. There are some valid situations in which you need to determine your state based on both props and a store's state. In those situations pass options `{withProps: true}` as the second argument to `create()`. This will expose the components props as the second argument to `calculateState()`. +- **Containers cannot access props** - By default containers are not able to access any props. This is both for performance reasons, and to ensure that containers are re-usable and props do not have to be threaded throughout a component tree. There are some valid situations in which you need to determine your state based on both props and a store's state. In those situations pass options `{withProps: true}` as the second argument to `create()`. This will expose the components props as the second argument to `calculateState()`. If you are unable to utilize react classes most of this functionality is also mirrored in a mixin. `import {Mixin} from 'flux/utils';` -# Using Flux with React Hooks +## Using Flux with React Hooks -React 16.8 introduced [Hooks](https://reactjs.org/docs/hooks-intro.html). Much of the functionality of flux and Flux Utils can be reproduced using [useContext](https://reactjs.org/docs/hooks-reference.html#usecontext) & [useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer). +React 16.8 introduced [Hooks](https://reactjs.org/docs/hooks-intro.html). Much of the functionality of Flux and Flux Utils can be reproduced using [useContext](https://reactjs.org/docs/hooks-reference.html#usecontext) & [useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer). -## Existing Projects with Store / ReduceStore +## Existing Projects with `Store`/`ReduceStore` If you have existing projects that need to continue using Flux Util's Stores, you can use the [flux-hooks](https://github.com/Fieldscope/flux-hooks) package. -Access the store using useFluxStore which provides an API similar to [Container](#container)'s calculateState. \ No newline at end of file +Access the store using useFluxStore which provides an API similar to [Container](#container)'s calculateState. diff --git a/docs/Immutable.ko-KR.md b/docs/Immutable.ko-KR.md deleted file mode 100644 index 1044c4a9..00000000 --- a/docs/Immutable.ko-KR.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: immutable-ko-KR -title: ImmutableJS – 불변 데이터 -layout: docs -category: Resources -permalink: http://facebook.github.io/immutable-js/ -next: jest-ko-KR -lang: ko-KR ---- diff --git a/docs/Immutable.md b/docs/Immutable.md deleted file mode 100644 index d4eac46e..00000000 --- a/docs/Immutable.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: immutable -title: ImmutableJS – Immutable Data -layout: docs -category: Resources -permalink: http://facebook.github.io/immutable-js/ -next: jest ---- diff --git a/docs/In-Depth-Overview.md b/docs/In-Depth-Overview.md index 2937c8fd..5bdcbece 100644 --- a/docs/In-Depth-Overview.md +++ b/docs/In-Depth-Overview.md @@ -1,53 +1,42 @@ --- id: in-depth-overview -title: In Depth Overview -layout: docs -category: Quick Start -permalink: docs/in-depth-overview.html -next: dispatcher +title: In-Depth Overview --- -Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code. +Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code. -
- +
+
-Flux applications have three major parts: the dispatcher, the stores, and the views (React components). These should not be confused with Model-View-Controller. Controllers do exist in a Flux application, but they are controller-views — views often found at the top of the hierarchy that retrieve data from the stores and pass this data down to their children. Additionally, action creators — dispatcher helper methods — are used to support a semantic API that describes all changes that are possible in the application. It can be useful to think of them as a fourth part of the Flux update cycle. +Flux applications have three major parts: the dispatcher, the stores, and the views (React components). These should not be confused with Model-View-Controller. Controllers do exist in a Flux application, but they are controller-views — views often found at the top of the hierarchy that retrieve data from the stores and pass this data down to their children. Additionally, action creators — dispatcher helper methods — are used to support a semantic API that describes all changes that are possible in the application. It can be useful to think of them as a fourth part of the Flux update cycle. Flux eschews MVC in favor of a unidirectional data flow. When a user interacts with a React view, the view propagates an action through a central dispatcher, to the various stores that hold the application's data and business logic, which updates all of the views that are affected. This works especially well with React's declarative programming style, which allows the store to send updates without specifying how to transition views between states. -We originally set out to deal correctly with derived data: for example, we wanted to show an unread count for message threads while another view showed a list of threads, with the unread ones highlighted. This was difficult to handle with MVC — marking a single thread as read would update the thread model, and then also need to update the unread count model. These dependencies and cascading updates often occur in a large MVC application, leading to a tangled weave of data flow and unpredictable results. +We originally set out to deal correctly with derived data: for example, we wanted to show an unread count for message threads while another view showed a list of threads, with the unread ones highlighted. This was difficult to handle with MVC — marking a single thread as read would update the thread model, and then also need to update the unread count model. These dependencies and cascading updates often occur in a large MVC application, leading to a tangled weave of data flow and unpredictable results. Control is inverted with stores: the stores accept updates and reconcile them as appropriate, rather than depending on something external to update its data in a consistent way. Nothing outside the store has any insight into how it manages the data for its domain, helping to keep a clear separation of concerns. Stores have no direct setter methods like `setAsRead()`, but instead have only a single way of getting new data into their self-contained world — the callback they register with the dispatcher. - ## Structure and Data Flow -

Data in a Flux application flows in a single direction: -

-
- unidirectional data flow in Flux +
+ Unidirectional data flow in Flux
-A unidirectional data flow is central to the Flux pattern, and the above diagram should be __the primary mental model for the Flux programmer__. The dispatcher, stores and views are independent nodes with distinct inputs and outputs. The actions are simple objects containing the new data and an identifying _type_ property. +A unidirectional data flow is central to the Flux pattern, and the above diagram should be **the primary mental model for the Flux programmer**. The dispatcher, stores and views are independent nodes with distinct inputs and outputs. The actions are simple objects containing the new data and an identifying _type_ property. -

The views may cause a new action to be propagated through the system in response to user interactions: -

- data flow in Flux with data originating from user interactions + data flow in Flux with data originating from user interactions
-

-All data flows through the dispatcher as a central hub. Actions are provided to the dispatcher in an action creator method, and most often originate from user interactions with the views. The dispatcher then invokes the callbacks that the stores have registered with it, dispatching actions to all stores. Within their registered callbacks, stores respond to whichever actions are relevant to the state they maintain. The stores then emit a change event to alert the controller-views that a change to the data layer has occurred. Controller-views listen for these events and retrieve data from the stores in an event handler. The controller-views call their own setState() method, causing a re-rendering of themselves and all of their descendants in the component tree. -

+All data flows through the dispatcher as a central hub. Actions are provided to the dispatcher in an _action creator_ method, and most often originate from user interactions with the views. The dispatcher then invokes the callbacks that the stores have registered with it, dispatching actions to all stores. Within their registered callbacks, stores respond to whichever actions are relevant to the state they maintain. The stores then emit a _change_ event to alert the controller-views that a change to the data layer has occurred. Controller-views listen for these events and retrieve data from the stores in an event handler. The controller-views call their own `setState()` method, causing a re-rendering of themselves and all of their descendants in the component tree.
- varying transports between each step of the Flux data flow + varying transports between each step of the Flux data flow
This structure allows us to reason easily about our application in a way that is reminiscent of _functional reactive programming_, or more specifically _data-flow programming_ or _flow-based programming_, where data flows through the application in a single direction — there are no two-way bindings. Application state is maintained only in the stores, allowing the different parts of the application to remain highly decoupled. Where dependencies do occur between stores, they are kept in a strict hierarchy, with synchronous updates managed by the dispatcher. @@ -56,25 +45,22 @@ We found that two-way data bindings led to cascading updates, where changing one Let's look at the various parts of Flux up close. A good place to start is the dispatcher. - ### A Single Dispatcher The dispatcher is the central hub that manages all data flow in a Flux application. It is essentially a registry of callbacks into the stores and has no real intelligence of its own — it is a simple mechanism for distributing the actions to the stores. Each store registers itself and provides a callback. When an action creator provides the dispatcher with a new action, all stores in the application receive the action via the callbacks in the registry. -As an application grows, the dispatcher becomes more vital, as it can be used to manage dependencies between the stores by invoking the registered callbacks in a specific order. Stores can declaratively wait for other stores to finish updating, and then update themselves accordingly. +As an application grows, the dispatcher becomes more vital, as it can be used to manage dependencies between the stores by invoking the registered callbacks in a specific order. Stores can declaratively wait for other stores to finish updating, and then update themselves accordingly. The same dispatcher that Facebook uses in production is available through [npm](https://www.npmjs.com/package/flux), [Bower](http://bower.io/), or [GitHub](https://github.com/facebook/flux). - ### Stores -Stores contain the application state and logic. Their role is somewhat similar to a model in a traditional MVC, but they manage the state of many objects — they do not represent a single record of data like ORM models do. Nor are they the same as Backbone's collections. More than simply managing a collection of ORM-style objects, stores manage the application state for a particular __domain__ within the application. +Stores contain the application state and logic. Their role is somewhat similar to a model in a traditional MVC, but they manage the state of many objects — they do not represent a single record of data like ORM models do. Nor are they the same as Backbone's collections. More than simply managing a collection of ORM-style objects, stores manage the application state for a particular **domain** within the application. -For example, Facebook's [Lookback Video Editor](https://facebook.com/lookback/edit) utilized a TimeStore that kept track of the playback time position and the playback state. On the other hand, the same application's ImageStore kept track of a collection of images. The TodoStore in our [TodoMVC example](https://github.com/facebook/flux/tree/master/examples/flux-todomvc/) is similar in that it manages a collection of to-do items. A store exhibits characteristics of both a collection of models and a singleton model of a logical domain. +For example, Facebook's [Lookback Video Editor](https://facebook.com/lookback/edit) utilized a TimeStore that kept track of the playback time position and the playback state. On the other hand, the same application's ImageStore kept track of a collection of images. The TodoStore in our [TodoMVC example](https://github.com/facebook/flux/tree/master/examples/flux-todomvc/) is similar in that it manages a collection of to-do items. A store exhibits characteristics of both a collection of models and a singleton model of a logical domain. As mentioned above, a store registers itself with the dispatcher and provides it with a callback. This callback receives the action as a parameter. Within the store's registered callback, a switch statement based on the action's type is used to interpret the action and to provide the proper hooks into the store's internal methods. This allows an action to result in an update to the state of the store, via the dispatcher. After the stores are updated, they broadcast an event declaring that their state has changed, so the views may query the new state and update themselves. - ### Views and Controller-Views React provides the kind of composable and freely re-renderable views we need for the view layer. Close to the top of the nested view hierarchy, a special kind of view listens for events that are broadcast by the stores that it depends on. We call this a controller-view, as it provides the glue code to get the data from the stores and to pass this data down the chain of its descendants. We might have one of these controller-views governing any significant section of the page. @@ -83,8 +69,7 @@ When it receives the event from the store, it first requests the new data it nee We often pass the entire state of the store down the chain of views in a single object, allowing different descendants to use what they need. In addition to keeping the controller-like behavior at the top of the hierarchy, and thus keeping our descendant views as functionally pure as possible, passing down the entire state of the store in a single object also has the effect of reducing the number of props we need to manage. -Occasionally we may need to add additional controller-views deeper in the hierarchy to keep components simple. This might help us to better encapsulate a section of the hierarchy related to a specific data domain. Be aware, however, that controller-views deeper in the hierarchy can violate the singular flow of data by introducing a new, potentially conflicting entry point for the data flow. In making the decision of whether to add a deep controller-view, balance the gain of simpler components against the complexity of multiple data updates flowing into the hierarchy at different points. These multiple data updates can lead to odd effects, with React's render method getting invoked repeatedly by updates from different controller-views, potentially increasing the difficulty of debugging. - +Occasionally we may need to add additional controller-views deeper in the hierarchy to keep components simple. This might help us to better encapsulate a section of the hierarchy related to a specific data domain. Be aware, however, that controller-views deeper in the hierarchy can violate the singular flow of data by introducing a new, potentially conflicting entry point for the data flow. In making the decision of whether to add a deep controller-view, balance the gain of simpler components against the complexity of multiple data updates flowing into the hierarchy at different points. These multiple data updates can lead to odd effects, with React's render method getting invoked repeatedly by updates from different controller-views, potentially increasing the difficulty of debugging. ### Actions @@ -92,10 +77,9 @@ The dispatcher exposes a method that allows us to trigger a dispatch to the stor Actions may also come from other places, such as the server. This happens, for example, during data initialization. It may also happen when the server returns an error code or when the server has updates to provide to the application. - ### What About that Dispatcher? -As mentioned earlier, the dispatcher is also able to manage dependencies between stores. This functionality is available through the `waitFor()` method within the Dispatcher class. We did not need to use this method within the extremely simple [TodoMVC application](https://github.com/facebook/flux/tree/master/examples/flux-todomvc/), but it becomes vital in a larger, more complex application. +As mentioned earlier, the dispatcher is also able to manage dependencies between stores. This functionality is available through the `waitFor()` method within the Dispatcher class. We did not need to use this method within the extremely simple [TodoMVC application](https://github.com/facebook/flux/tree/master/examples/flux-todomvc/), but it becomes vital in a larger, more complex application. Within the TodoStore's registered callback we could explicitly wait for any dependencies to first update before moving forward: @@ -115,7 +99,7 @@ case 'TODO_CREATE': A dispatch token is returned by `register()` when registering callbacks for the Dispatcher: ```javascript -PrependedTextStore.dispatchToken = Dispatcher.register(function (payload) { +PrependedTextStore.dispatchToken = Dispatcher.register(function(payload) { // ... }); ``` diff --git a/docs/Jest.ko-KR.md b/docs/Jest.ko-KR.md deleted file mode 100644 index b479a3af..00000000 --- a/docs/Jest.ko-KR.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: jest-ko-KR -title: Jest – 단위 테스팅 -layout: docs -category: Resources -permalink: http://facebook.github.io/jest/ -lang: ko-KR ---- diff --git a/docs/Jest.md b/docs/Jest.md deleted file mode 100644 index 94fc73d6..00000000 --- a/docs/Jest.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: jest -title: Jest – Unit Testing -layout: docs -category: Resources -permalink: http://facebook.github.io/jest/ ---- diff --git a/docs/Overview.ko-KR.md b/docs/Overview.ko-KR.md index 3a6d1e95..acfd2c31 100644 --- a/docs/Overview.ko-KR.md +++ b/docs/Overview.ko-KR.md @@ -3,7 +3,6 @@ id: overview-ko-KR title: 개요 layout: docs category: Quick Start -permalink: docs/overview-ko-KR.html next: dispatcher-ko-KR lang: ko-KR --- @@ -32,7 +31,7 @@ Flux 애플리케이션에서의 데이터는 단방향으로 흐른다: Flux에서의 단방향 데이터 흐름
-단방향 데이터 흐름은 Flux 패턴의 핵심인데 위 다이어그램은 __Flux 프로그래머를 위한 제일의 멘탈 모델__이 된다. dispatcher, store와 view는 독립적인 노드로 입력과 출력이 완전히 구분된다. action은 새로운 데이터를 포함하고 있는 간단한 객체로 _type_ 프로퍼티로 구분할 수 있다. +단방향 데이터 흐름은 Flux 패턴의 핵심인데 위 다이어그램은 **Flux 프로그래머를 위한 제일의 멘탈 모델**이 된다. dispatcher, store와 view는 독립적인 노드로 입력과 출력이 완전히 구분된다. action은 새로운 데이터를 포함하고 있는 간단한 객체로 _type_ 프로퍼티로 구분할 수 있다.

view는 사용자의 상호작용에 응답하기 위해 새로운 action을 만들어 시스템에 전파한다: @@ -50,7 +49,7 @@ view는 사용자의 상호작용에 응답하기 위해 새로운 action을 만 flux 데이터 흐름의 각각 순서에서 다양하게 전달되는 데이터

-Action creator는 라이브러리에서 제공하는 도움 메소드로 메소드 파라미터에서 action을 생성하고 _type_을 설정하거나 dispatcher에게 제공하는 역할을 한다. +Action creator는 라이브러리에서 제공하는 도움 메소드로 메소드 파라미터에서 action을 생성하고 *type*을 설정하거나 dispatcher에게 제공하는 역할을 한다. 모든 action은 store가 dispatcher에 등록해둔 callback을 통해 모든 store에 전송된다. @@ -60,7 +59,7 @@ controller-view라고 불리는 특별한 view가 변경 이벤트를 듣고 새 이 구조는 함수형 반응 프로그래밍을 다시 재현하는 것을 쉽게 만들거나 데이터-흐름 프로그래밍, 흐름 기반 프로그래밍을 만드는데 쉽도록 돕는다. 애플리케이션에 흐르는 데이터 흐름이 양방향 바인딩이 아닌 단방향으로 흐르기 때문이다. 애플리케이션의 상태는 store에 의해서 관리되고 애플리케이션의 다른 부분과는 완전히 분리된 상태로 남는다. 두 store 사이에 의존성이 나타나도 둘은 엄격하게 위계가 관리되어 dispatcher에 의해 동기적으로 변경되는 방법으로 관리된다. -이와 같은 구조는 우리의 애플리케이션이 _함수형 반응 프로그래밍(functional reactive programming)_이나 더 세부적으로 _데이터-흐름 프로그래밍(data-flow programming)_ 또는 _흐름 기반 프로그래밍(Flow-based programming)_을 연상하게 한다는 사실을 쉽게 떠올리게 한다. 즉 데이터의 흐름이 양방향 바인딩이 아닌 단일 방향으로 흐른다. 애플리케이션의 상태는 store에 의해 관리를 해서 애플리케이션의 다른 부분들과 결합도를 극히 낮춘 상태로 유지될 수 있다. store의 사이에서 의존성이 생긴다고 해도 dispachter에 의해 엄격한 위계가 유지되어 동기적으로 갱신되는 방식으로 관리된다. +이와 같은 구조는 우리의 애플리케이션이 *함수형 반응 프로그래밍(functional reactive programming)*이나 더 세부적으로 _데이터-흐름 프로그래밍(data-flow programming)_ 또는 *흐름 기반 프로그래밍(Flow-based programming)*을 연상하게 한다는 사실을 쉽게 떠올리게 한다. 즉 데이터의 흐름이 양방향 바인딩이 아닌 단일 방향으로 흐른다. 애플리케이션의 상태는 store에 의해 관리를 해서 애플리케이션의 다른 부분들과 결합도를 극히 낮춘 상태로 유지될 수 있다. store의 사이에서 의존성이 생긴다고 해도 dispachter에 의해 엄격한 위계가 유지되어 동기적으로 갱신되는 방식으로 관리된다. 양방향 데이터 바인딩은 연속적인 갱신이 발생하고 객체 하나의 변경이 다른 객체를 변경하게 되어 실제 필요한 업데이트보다 더 많은 분량을 실행하게 된다. 애플리케이션의 규모가 커지면 데이터의 연속적인 갱신이 되는 상황에서는 사용자 상호작용의 결과가 어떤 변화를 만드는지 예측하는데 어려워진다. 갱신으로 인한 데이터 변경이 단 한 차례만 이뤄진다면 전체 시스템은 좀 더 예측 가능하게 된다. @@ -76,7 +75,7 @@ Facebook이 실제로 사용하는 dispatcher는 [npm](https://www.npmjs.com/pac ### Stores -Store는 애플리케이션의 상태와 로직을 포함하고 있다. store의 역할은 전통적인 MVC의 모델과 비슷하지만 많은 객체의 상태를 관리할 수 있는데 ORM 모델이 하는 것처럼 단일 레코드의 데이터를 표현하는 것도 아니고 Backbone의 컬렉션과도 다르다. store는 단순히 ORM 스타일의 객체 컬렉션을 관리하는 것을 넘어 애플리케이션 내의 개별적인 __도메인__에서 애플리케이션의 상태를 관리한다. +Store는 애플리케이션의 상태와 로직을 포함하고 있다. store의 역할은 전통적인 MVC의 모델과 비슷하지만 많은 객체의 상태를 관리할 수 있는데 ORM 모델이 하는 것처럼 단일 레코드의 데이터를 표현하는 것도 아니고 Backbone의 컬렉션과도 다르다. store는 단순히 ORM 스타일의 객체 컬렉션을 관리하는 것을 넘어 애플리케이션 내의 개별적인 **도메인**에서 애플리케이션의 상태를 관리한다. 예를 들면, Facebook의 [돌아보기 편집기](https://facebook.com/lookback/edit) 에서 지속해서 재생된 시간과 플레이어 상태를 지속해서 추적하기 위해 TimeStore를 활용한다. 같은 애플리케이션에서 ImageStore는 이미지 콜랙션을 지속해서 추적한다. [TodoMVC 예제](https://github.com/facebook/flux/tree/master/examples/flux-todomvc/)의 TodoStore도 비슷하게 할 일 항목의 콜랙션을 관리한다. store는 두 모델 컬렉션의 특징을 보여주는 것과 동시에 싱글턴 모델의 논리적 도메인으로 역할을 한다. @@ -97,11 +96,10 @@ store에게 이벤트를 받으면 store의 퍼블릭 getter 메소드를 통해 ### Actions -dispatcher는 action을 호출해 데이터를 불러오고 store로 전달할 수 있도록 메소드를 제공한다. action의 생성은 dispatcher로 action을 보낼 때 의미 있는 헬퍼 메소드로 포개진다. 할 일 목록 애플리케이션에서 할 일 아이템의 문구를 변경하고 싶다고 가정하자. `updateText(todoId, newText)`와 같은 함수 시그니처를 이용해 `TodoActions` 모듈 내에 action을 만든다. 이 메소드는 view의 이벤트 핸들러로부터 호출되어 실행할 수 있고 그 결과로 사용자 상호작용에 응답할 수 있게 된다. 이 action creator 메소드는 _type_을 추가할 수 있다. 이 type을 이용해 action이 store에서 해석될 수 있도록, 적절한 응답이 가능하도록 한다. 예시에서와같이 `TODO_UPDATE_TEXT`와 같은 이름의 타입을 사용한다. +dispatcher는 action을 호출해 데이터를 불러오고 store로 전달할 수 있도록 메소드를 제공한다. action의 생성은 dispatcher로 action을 보낼 때 의미 있는 헬퍼 메소드로 포개진다. 할 일 목록 애플리케이션에서 할 일 아이템의 문구를 변경하고 싶다고 가정하자. `updateText(todoId, newText)`와 같은 함수 시그니처를 이용해 `TodoActions` 모듈 내에 action을 만든다. 이 메소드는 view의 이벤트 핸들러로부터 호출되어 실행할 수 있고 그 결과로 사용자 상호작용에 응답할 수 있게 된다. 이 action creator 메소드는 *type*을 추가할 수 있다. 이 type을 이용해 action이 store에서 해석될 수 있도록, 적절한 응답이 가능하도록 한다. 예시에서와같이 `TODO_UPDATE_TEXT`와 같은 이름의 타입을 사용한다. action은 서버와 같은 다른 장소에서 올 수 있다. 예를 들면 data를 초기화할 때 이런 과정이 발생할 수 있다. 또한, 서버에서 에러 코드를 반환하거나 애플리케이션이 제공된 후에 업데이트가 있을 때 나타날 수 있다. - ### Dispatcher에 대해서 앞서 언급한 것처럼 disaptcher는 store 간의 의존성을 관리할 수 있다. 이 기능은 dispatcher 클래스에 포함된 `waitFor()` 메소드를 통해 가능하다. [TodoMVC](https://github.com/facebook/flux/tree/master/examples/flux-todomvc/)는 극단적으로 단순해서 이 메소드를 사용할 필요가 없지만 복잡한 대형 애플리케이션에서는 생명과도 같다. @@ -119,12 +117,12 @@ case 'TODO_CREATE': break; ``` -`waitFor()`는 단일 인수만 받는데 disaptcher에 등록된 인덱스를 배열로 받는다. 이 인덱스를 대개 _dispatch token_이라 부른다. 그러므로 `waitForm()`을 호출하는 store는 다른 store의 상태에 따라 어떤 방식으로 자신의 상태를 갱신할 수 있는지 알 수 있게 된다. +`waitFor()`는 단일 인수만 받는데 disaptcher에 등록된 인덱스를 배열로 받는다. 이 인덱스를 대개 *dispatch token*이라 부른다. 그러므로 `waitForm()`을 호출하는 store는 다른 store의 상태에 따라 어떤 방식으로 자신의 상태를 갱신할 수 있는지 알 수 있게 된다. dispatch token은 `register()` 메소드에서 반환하는데 이 메소드는 callback을 dispatcher에 등록할 때 사용된다: ```javascript -PrependedTextStore.dispatchToken = Dispatcher.register(function (payload) { +PrependedTextStore.dispatchToken = Dispatcher.register(function(payload) { // ... }); ``` diff --git a/docs/Overview.md b/docs/Overview.md index 75262c34..5308f056 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -3,12 +3,11 @@ id: overview title: Overview layout: docs category: Quick Start -permalink: docs/overview.html next: in-depth-overview --- -In order to get started check out the [overview and guides](https://github.com/facebook/flux/tree/master/examples) maintained on Github. - -Or continue on to the in-depth overview, which explores in more detail how the pieces of the Flux architecture work together. - -_(Note: The In Depth Overview was formerly the normal Overview landing page but was replaced with the more terse and up-to-date guides on Github that are linked above.)_ +In order to get started check out the [overview and guides](https://github.com/facebook/flux/tree/master/examples) maintained on Github. + +Or continue on to the in-depth overview, which explores in more detail how the pieces of the Flux architecture work together. + +> Note: The In Depth Overview was formerly the normal Overview landing page but was replaced with the more terse and up-to-date guides on GitHub that are linked above. diff --git a/docs/React.ko-KR.md b/docs/React.ko-KR.md deleted file mode 100644 index 5ad142b7..00000000 --- a/docs/React.ko-KR.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: react-ko-KR -title: React – UI 라이브러리 -layout: docs -category: Resources -permalink: http://reactkr.github.io/react/ -next: immutable-ko-KR -lang: ko-KR ---- diff --git a/docs/React.md b/docs/React.md deleted file mode 100644 index 810b2ee7..00000000 --- a/docs/React.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -id: react -title: React – UI Library -layout: docs -category: Resources -permalink: http://facebook.github.io/react/ -next: immutable ---- diff --git a/docs/Related-Libraries.md b/docs/Related-Libraries.md new file mode 100644 index 00000000..d7d4d4ff --- /dev/null +++ b/docs/Related-Libraries.md @@ -0,0 +1,46 @@ +--- +id: related-libraries +title: Related Libraries +--- + +### React – User Interfaces + +If any JavaScript project has taken the front end ecosystem by storm in recent years, that would be [React](https://reactjs.org). React is a library built and open-sourced by the smart people at Facebook. In React, developers write components for their web interface and compose them together. + +React brings about many radical ideas and encourages developers to [rethink best practices](https://www.youtube.com/watch?v=DgVS-zXgMTk). For many years, web developers were taught that it was a good practice to write HTML, JavaScript and CSS separately. React does the exact opposite, and encourages that you write your HTML and [CSS in your JavaScript](https://speakerdeck.com/vjeux/react-css-in-js) instead. This sounds like a crazy idea at first, but after trying it out, it actually isn't as weird as it sounds initially. Reason being the front end development scene is shifting towards a paradigm of component-based development. The features of React: + +- **Declarative** - You describe what you want to see in your view and not how to achieve it. In the jQuery days, developers would have to come up with a series of steps to manipulate the DOM to get from one app state to the next. In React, you simply change the state within the component and the view will update itself according to the state. It is also easy to determine how the component will look like just by looking at the markup in the `render()` method. + +- **Functional** - The view is a pure function of `props` and `state`. In most cases, a React component is defined by `props` (external parameters) and `state` (internal data). For the same `props` and `state`, the same view is produced. Pure functions are easy to test, and the same goes for functional components. Testing in React is made easy because a component's interfaces are well-defined and you can test the component by supplying different `props` and `state` to it and comparing the rendered output. + +- **Maintainable** - Writing your view in a component-based fashion encourages reusability. We find that defining a component's `propTypes` make React code self-documenting as the reader can know clearly what is needed to use that component. Lastly, your view and logic is self-contained within the component, and should not be affected nor affect other components. That makes it easy to shift components around during large-scale refactoring, as long as the same `props` are supplied to the component. + +- **High Performance** - You might have heard that React uses a virtual DOM (not to be confused with [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)) and it re-renders everything when there is a change in state. Why is there a need for a virtual DOM? While modern JavaScript engines are fast, reading from and writing to the DOM is slow. React keeps a lightweight virtual representation of the DOM in memory. Re-rendering everything is a misleading term. In React it actually refers to re-rendering the in-memory representation of the DOM, not the actual DOM itself. When there's a change in the underlying data of the component, a new virtual representation is created, and compared against the previous representation. The difference (minimal set of changes required) is then patched to the real browser DOM. + +- **Ease of Learning** - Learning React is pretty simple. The React API surface is relatively small compared to [this](https://angular.io/docs/ts/latest/api/); there are only a few APIs to learn and they do not change often. The React community is one of the largest, and along with that comes a vibrant ecosystem of tools, open-sourced UI components, and a ton of great resources online to get you started on learning React. + +- **Developer Experience** - There are a number of tools that improves the development experience with React. [React Developer Tools](https://github.com/facebook/react-devtools) is a browser extension that allows you to inspect your component, view and manipulate its `props` and `state`. [Hot reloading](https://github.com/gaearon/react-hot-loader) with webpack allows you to view changes to your code in your browser, without you having to refresh the browser. Front end development involves a lot of tweaking code, saving and then refreshing the browser. Hot reloading helps you by eliminating the last step. When there are library updates, Facebook provides [codemod scripts](https://github.com/reactjs/react-codemod) to help you migrate your code to the new APIs. This makes the upgrading process relatively pain-free. Kudos to the Facebook team for their dedication in making the development experience with React great. + +### Immutable.js – Immutable Data + +[Immutable.js](https://immutable-js.github.io/immutable-js/) is a library for creating immutable data structues. Immutable data cannot be changed once created, leading to much simpler application development, no defensive copying, and enabling advanced memoization and change detection techniques with simple logic. Persistent data presents a mutative API which does not update the data in-place, but instead always yields new updated data. + +### Jest – Unit Testing + +[Jest](http://facebook.github.io/jest/) is a testing library by Facebook that aims to make the process of testing pain-free. As with Facebook projects, it provides a great development experience out of the box. Tests can be run in parallel resulting in shorter duration. During watch mode, by default, only the tests for the changed files are run. One cool feature is "Snapshot Testing". Jest can save the generated output of your React component and Redux state and save it as serialized files, so you wouldn't have to manually come up with the expected output yourself. Jest also comes with built-in mocking, assertion and test coverage. One library to rule them all! + +### Redux - Alternative State Management + +As Flux is not a framework per se, developers have tried to come up with many implementations of the Flux pattern. Eventually, a clear winner emerged, which was [Redux](http://redux.js.org/). Redux combines the ideas from Flux, [Command pattern](https://www.wikiwand.com/en/Command_pattern) and [Elm architecture](https://guide.elm-lang.org/architecture/) and is the de facto state management library developers use with React these days. Its core concepts are: + +- App **state** is described by a single plain old JavaScript object (POJO). +- Dispatch an **action** (also a POJO) to modify the state. +- **Reducer** is a pure function that takes in current state and action to produce a new state. + +The concepts sound simple, but they are really powerful as they enable apps to: + +- Have their state rendered on the server, booted up on the client. +- Trace, log and backtrack changes in the whole app. +- Implement undo/redo functionality easily. + +The creator of Redux, [Dan Abramov](https://github.com/gaearon), has taken great care in writing up detailed documentation for Redux, along with creating comprehensive video tutorials for learning [basic](https://egghead.io/courses/getting-started-with-redux) and [advanced](https://egghead.io/courses/building-react-applications-with-idiomatic-redux) Redux. They are extremely helpful resources for learning Redux. diff --git a/docs/Videos.ko-KR.md b/docs/Videos.ko-KR.md index b8768ab2..9468581b 100644 --- a/docs/Videos.ko-KR.md +++ b/docs/Videos.ko-KR.md @@ -1,14 +1,9 @@ --- id: videos-ko-KR title: 비디오 -layout: docs -category: Resources -permalink: docs/videos-ko-KR.html -next: react-ko-KR -lang: ko-KR --- -### "Rethinking Web App Development at Facebook" - Facebook F8 Conference 2014 +### Rethinking Web App Development at Facebook - Facebook F8 Conference 2014
diff --git a/docs/Videos.md b/docs/Videos.md index 7aeb5414..1fba51ac 100644 --- a/docs/Videos.md +++ b/docs/Videos.md @@ -1,13 +1,9 @@ --- id: videos title: Videos -layout: docs -category: Resources -permalink: docs/videos.html -next: react --- -### "Rethinking Web App Development at Facebook" - Facebook F8 Conference 2014 +### Rethinking Web App Development at Facebook - Facebook F8 Conference 2014
diff --git a/docusaurus/website/core/Footer.js b/docusaurus/website/core/Footer.js deleted file mode 100755 index 713eb360..00000000 --- a/docusaurus/website/core/Footer.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -class Footer extends React.Component { - docUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - const docsUrl = this.props.config.docsUrl; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - return `${baseUrl}${docsPart}${langPart}${doc}`; - } - - pageUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - return baseUrl + (language ? `${language}/` : '') + doc; - } - - render() { - return ( - - ); - } -} - -module.exports = Footer; diff --git a/docusaurus/website/package.json b/docusaurus/website/package.json deleted file mode 100644 index 47eb86d8..00000000 --- a/docusaurus/website/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "scripts": { - "examples": "flux website", - "start": "docusaurus-start", - "build": "docusaurus-build", - "publish-gh-pages": "docusaurus-publish", - "write-translations": "docusaurus-write-translations", - "version": "docusaurus-version", - "rename-version": "docusaurus-rename-version" - }, - "devDependencies": { - "docusaurus": "^1.6.2" - } -} diff --git a/docusaurus/website/pages/en/help.js b/docusaurus/website/pages/en/help.js deleted file mode 100755 index 66058daa..00000000 --- a/docusaurus/website/pages/en/help.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -const CompLibrary = require('../../core/CompLibrary.js'); - -const Container = CompLibrary.Container; -const GridBlock = CompLibrary.GridBlock; - -function Help(props) { - const {config: siteConfig, language = ''} = props; - const {baseUrl, docsUrl} = siteConfig; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; - - const supportLinks = [ - { - content: `Many members of the community use Stack Overflow to ask questions. Read through the [existing questions](https://stackoverflow.com/questions/tagged/reactjs) tagged with reactjs or [ask your own!](https://stackoverflow.com/questions/ask)`, - title: 'StackOverflow', - }, - { - content: '[The reactjs Google Group](https://groups.google.com/forum/#!forum/reactjs) is also a good place to ask questions and find answers.', - title: 'Google Groups mailing list', - }, - { - content: 'Many developers and users idle on Freenode.net\'s IRC network in [#reactjs on freenode.](irc://chat.freenode.net/reactjs)', - title: 'IRC', - }, - { - content: '[#fluxjs hash tag on Twitter](https://twitter.com/search?q=%23fluxjs) is used to keep up with the latest Flux news.', - title: 'Twitter', - } - ]; - - return ( -
- -
-
-

Need help?

-
-

Flux is worked on full-time by Facebook's product infrastructure user interface engineering teams. They're often around and available for questions.

- -
-
-
- ); -} - -module.exports = Help; diff --git a/docusaurus/website/pages/en/index.js b/docusaurus/website/pages/en/index.js deleted file mode 100755 index 370788cf..00000000 --- a/docusaurus/website/pages/en/index.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -const CompLibrary = require('../../core/CompLibrary.js'); - -const Container = CompLibrary.Container; -const GridBlock = CompLibrary.GridBlock; - -class HomeSplash extends React.Component { - render() { - const {siteConfig, language = ''} = this.props; - const {baseUrl, docsUrl} = siteConfig; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; - - const SplashContainer = props => ( -
-
-
{props.children}
-
-
- ); - - const ProjectTitle = () => ( -

- {siteConfig.title} - {siteConfig.tagline} -

- ); - - const PromoSection = props => ( -
-
-
{props.children}
-
-
- ); - - const Button = props => ( - - ); - - const Description = () => ( -
- Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code. -
- ) - - const Video = () => ( - - ) - - return ( - -
- - -
-
- ); - } -} - -class Index extends React.Component { - render() { - const {config: siteConfig, language = ''} = this.props; - const {baseUrl} = siteConfig; - - const Block = props => ( - - - - ); - - return ; - } -} - -module.exports = Index; diff --git a/docusaurus/website/sidebars.json b/docusaurus/website/sidebars.json deleted file mode 100755 index 7dc3d461..00000000 --- a/docusaurus/website/sidebars.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "docs": { - "Quick Start": [ - "overview", - "in-depth-overview" - ], - "Reference": [ - "dispatcher", - "flux-utils" - ], - "Resources": [ - "videos" - ] - } -} diff --git a/docusaurus/website/siteConfig.js b/docusaurus/website/siteConfig.js deleted file mode 100755 index 1b54dd1a..00000000 --- a/docusaurus/website/siteConfig.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const siteConfig = { - title: "Flux", - tagline: "Application architecture for building user interfaces", - url: "http://facebook.github.io/flux/", - baseUrl: "/flux/", - projectName: "flux", - - headerLinks: [ - { doc: "overview", label: "Docs" }, - { href: "/flux/help", label: "Support" }, - { href: "https://github.com/facebook/flux", label: "GitHub" } - ], - - headerIcon: "img/logo/flux-logo-white.svg", - footerIcon: "img/logo/flux-logo-white.svg", - favicon: "img/favicon.png", - - colors: { - primaryColor: "#318435", - secondaryColor: "#205C3B" - }, - - fonts: { - myFont: [ - "proxima-nova", - "Helvetica Neue", - "Helvetica", - "Arial", - "sans-serif" - ] - }, - - copyright: `Copyright © 2014-${new Date().getFullYear()} Facebook Inc.`, - - highlight: { - theme: "atom-one-dark" - }, - - scripts: ["https://buttons.github.io/buttons.js"], - onPageNav: "separate", - cleanUrl: true, - ogImage: "img/docusaurus.png", - twitterImage: "img/docusaurus.png", - enableUpdateTime: true, - repoUrl: 'https://github.com/facebook/flux', -}; - -module.exports = siteConfig; diff --git a/docusaurus/website/static/css/custom.css b/docusaurus/website/static/css/custom.css deleted file mode 100755 index 12907601..00000000 --- a/docusaurus/website/static/css/custom.css +++ /dev/null @@ -1,55 +0,0 @@ -/* your custom css */ - -.homeContainer { - background-color: #f0f0f0; - background-image: linear-gradient(to right bottom, #07341d, #00322a, #003035, #002c3c, #00273d, #0a2338, #111f33, #151b2e, #161826, #15161f, #131318, #101010); -} - -.homeDescription { - width: 50%; - margin: 0 auto; - max-width: 700px; - color: #c4c4c4; - font-weight: 100; -} - -.fluxLogo { - max-width: 200px; - margin: 0 auto; -} - -.homeVideo { - margin-top: 1.3em; - width: 560px; -} - -.projectTitle { - color: #f5f5f5; -} - -.homeButton { - border: 1px solid #e3e3e3; - color: #e3e3e3; -} - -@media only screen and (min-device-width: 360px) and (max-device-width: 736px) { - .homeVideo { - max-width: 90%; - } - - .homeDescription { - width: 90%; - } -} - -@media only screen and (min-width: 1024px) { -} - -@media only screen and (max-width: 1023px) { -} - -@media only screen and (min-width: 1400px) { -} - -@media only screen and (min-width: 1500px) { -} \ No newline at end of file diff --git a/docusaurus/website/static/img/docusaurus.svg b/docusaurus/website/static/img/docusaurus.svg deleted file mode 100755 index f80b2217..00000000 --- a/docusaurus/website/static/img/docusaurus.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docusaurus/website/static/img/favicon/favico.ico b/docusaurus/website/static/img/favicon/favico.ico deleted file mode 100644 index 96bafe8a..00000000 Binary files a/docusaurus/website/static/img/favicon/favico.ico and /dev/null differ diff --git a/docs/img/flux-diagram-white-background.png b/img/flux-diagram-white-background.png similarity index 100% rename from docs/img/flux-diagram-white-background.png rename to img/flux-diagram-white-background.png diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 00000000..1b34df51 --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,20 @@ +# dependencies +/node_modules + +# production +/build + +# generated files +.docusaurus +.cache-loader + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js new file mode 100644 index 00000000..88f7e3f1 --- /dev/null +++ b/website/docusaurus.config.js @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +module.exports = { + title: 'Flux', + tagline: 'Application architecture for building user interfaces', + url: 'https://facebook.github.io', + baseUrl: '/flux/', + favicon: 'img/favicon.ico', + themeConfig: { + navbar: { + title: 'Flux', + logo: { + alt: 'Flux Logo', + src: 'img/flux-logo-color.svg', + }, + links: [ + { to: 'docs/overview', label: 'Docs', position: 'left' }, + { to: 'support', label: 'Support', position: 'left' }, + { + href: 'https://github.com/facebook/flux', + label: 'GitHub', + position: 'right', + }, + ], + }, + footer: { + style: 'dark', + logo: { + alt: 'Facebook Open Source Logo', + src: 'https://docusaurus.io/img/oss_logo.png', + }, + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc. Built with Docusaurus.`, + }, + }, + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + path: '../docs', + sidebarPath: require.resolve('./sidebars.js'), + }, + pages: { + path: 'src/pages', + }, + theme: { + customCss: require.resolve('./src/css/custom.css'), + }, + }, + ], + ], +}; diff --git a/website/package.json b/website/package.json new file mode 100644 index 00000000..6ab85904 --- /dev/null +++ b/website/package.json @@ -0,0 +1,31 @@ +{ + "name": "flux-website", + "version": "0.0.1", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy" + }, + "dependencies": { + "@docusaurus/core": "^2.0.0-alpha.19", + "@docusaurus/preset-classic": "^2.0.0-alpha.19", + "classnames": "^2.2.6", + "react": "^16.8.4", + "react-dom": "^16.8.4" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/website/sidebars.js b/website/sidebars.js new file mode 100644 index 00000000..26b560de --- /dev/null +++ b/website/sidebars.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +module.exports = { + docs: { + 'Quick Start': ['overview', 'in-depth-overview'], + Reference: ['dispatcher', 'flux-utils'], + Resources: ['videos', 'related-libraries'], + }, +}; diff --git a/website/src/css/custom.css b/website/src/css/custom.css new file mode 100644 index 00000000..3cf6b2fc --- /dev/null +++ b/website/src/css/custom.css @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * Any CSS included here will be global. The classic template + * bundles Infima by default. Infima is a CSS framework designed to + * work well for content-centric websites. + */ + +/* You can override the default Infima variables here. */ +:root { + --ifm-color-primary: #318435; + --ifm-color-primary-dark: rgb(44, 119, 48); + --ifm-color-primary-darker: rgb(42, 112, 45); + --ifm-color-primary-darkest: rgb(34, 92, 37); + --ifm-color-primary-light: rgb(80, 150, 83); + --ifm-color-primary-lighter: rgb(111, 169, 114); + --ifm-color-primary-lightest: rgb(152, 194, 154); +} + +.navbar .navbar__logo { + height: auto; + width: 50px; +} + +.video-container { + height: 0; + margin: 0; + margin-bottom: 30px; + overflow: hidden; + padding-bottom: 56.25%; + padding-top: 30px; + position: relative; +} + +.video-container iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} diff --git a/website/src/pages/index.js b/website/src/pages/index.js new file mode 100644 index 00000000..d7e722e7 --- /dev/null +++ b/website/src/pages/index.js @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import classnames from 'classnames'; +import Layout from '@theme/Layout'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import withBaseUrl from '@docusaurus/withBaseUrl'; +import styles from './styles.module.css'; + +const features = [ + { + title: <>What is Flux?, + imageUrl: 'img/undraw_building_blocks.svg', + description: ( + <> + Flux is the application architecture that Facebook uses for building + client-side web applications. + + ), + }, + { + title: <>What does it do?, + imageUrl: 'img/undraw_react.svg', + description: ( + <> + It complements React's composable view components by utilizing a + unidirectional data flow. + + ), + }, + { + title: <>How do I use it?, + imageUrl: 'img/undraw_programming.svg', + description: ( + <> + It's more of a pattern rather than a formal framework, and you can start + using Flux immediately without a lot of new code. + + ), + }, +]; + +function Home() { + const context = useDocusaurusContext(); + const { siteConfig = {} } = context; + + return ( + +
+
+

{siteConfig.title}

+

{siteConfig.tagline}

+
+ + Get Started + +
+
+
+
+ {features && features.length && ( +
+
+
+ {features.map(({ imageUrl, title, description }, idx) => ( +
+ {imageUrl && ( +
+ {title} +
+ )} +

{title}

+

{description}

+
+ ))} +
+
+
+ )} +
+
+
+

Introduction Video

+