I have been creating a React calendar. At first I just wanted to declare the calendar in the html with the appointments, like this:
<Calendar appts={appts} />
But then I realized that my calendar was going to have to be a full app, talking to the REST endpoints and have it's own store and actions.
The calendar was not the end goal, and now I need it to be part of a bigger 'Flux' app. How is everyone architecting their apps, so that the pieces can be reused, say the calendar, in other apps? How do the different Flux apps talk to each other? Are there any examples or blog posts where this is talked about?
Flux is an publisher-subscriber architecture recommendation from Facebook. RefluxJS is an easy to use implementation of this architecture. It adds actions and stores to ReactJS.
Actions are triggers for change. Whenever the user interacts with the page you call an action. Actions have almost completely replaced setState inside a React component for me. When a user creates an event such as a form field change, I fire an action with the event data as a function parameter. In this architecture, actions allow React components (classes) to broadcast publish changes.
Stores subscribe (listen) to actions. The simplest store simply passes on parameters that have changed with a this.trigger call. Other stores may listen to other stores, validate data, stuff parameters into data, set data into an object, or push data onto an array than broadcast the new dataset with a this.trigger call.
React components (classes) and stores can subscribe (listen) to stores. When these stores update, you can
Update state and all dependent props
Do something with the updated store dataset
Reflux comes with a very useful connect mixin which allows you to link the state of a class to a store. Be careful though, be sure to implement getInitialState in the store if you do this. Otherwise, your class will start with a null state. Another useful mixin is the ListenerMixin if you just want the component to do something when a store changes.
For more information, be sure to checkout the RefluxJS README.
Related
I am working on a React application and use react-redux and redux-thunk for integration with redux for state management.
I want to display a modal whenever I add a new entity. The ideal solution from my point of view seems to be:
In the action creator where I add the entity, the redux state should be updated with the notification message if the operation was succesfull
The main component of the app (The App component) should somehow listen to the redux state, and whenever a notifications message appears it should render the modal with the message.
I do not have an idea on how to implement the second point (how to subscribe the main component to state change and react accordingly).
On another note, there might be a better alternative to implement the notification component so I will gladly listen to alternative solutions as my exposure to front end development and React is quite limited.
First thing is that you probably want to display a "Snackbar" component (Example from Material-ui), and not a dialog as you probably might have several entities created one after the other, and you don't want to flicker the dialogs to the user...
Regarding the redux store, I think you should have a specific part in your store to hold all the notifications (Array of notifications), And every time a message with new entity comes you add a notification to the array. And after some time (Say 5sec) you remove the notification from the array.
In the ui, your component should listen to this part of the store, and just display the Snackbars one after the other.
I'm building a real-time "lobby" type web app that hosts multiple users (2-8 at a time), where the state of the lobby is shared among the users. The UI is built with React. Each user establishes a websocket connection to the backend upon joining the lobby. At this time they receive the full global state of the app as a JSON object (its size should not exceed a few kilobytes).
I'm having difficulties conceptualizing the precise state maintenance scheme, and would like to hear your views about it, once I've described the situation in more detail.
The lobby presents to the users a number of finite resource pools, access to which is shared by everyone. The users will move these resources between each other as well as to and from the pools. My current thinking is that the full state of the lobby and all of its resource pools is stored and maintained exclusively in the backend. When a user wants to move a resource e.g. from a pool to themselves or vice versa, or to change the visible state of a resource, this is done with JSON messages sent over their respective websocket connections.
Each action they perform causes a message like this to be sent over the socket (simplified):
{
"action": "MOVE",
"source": "POOL1",
"target": "user_id_here",
...metadata...
}
The users send these messages concurrently at arbitrary times and intervals, and the backend (using a Python asyncio-based server and a data store still to be determined) receives them serially, reconciles each one with the global state in the order they arrived, and then sends the full updated state of the app to every user over their websocket connections, for every single message received. The user who performed the action that triggered the state update additionally gets a status object informing them of a successful transaction, which the UI can then indicate to them.
When a user sends an action message that is impossible to reconcile (e.g. another user has exhausted a resource pool just before their message requesting a resource from that same pool came in), the app still sends them the full up-to-date state of the app, but a status object is included, containing information that the UI uses to inform them that their action could not be performed.
So far, so good. Given the types of actions, types of resource pools, number of users and size of state objects that are to be expected, the frequency of updates should not become a problem, neither in terms of resources nor bandwidth use.
To clarify: none of the actions that the users perform in the React UI mutate their local state in any way. Each and every action they perform is translated into a JSON message like the example above, and the result of that action will be receiving the updated full state of the app, which fully replaces the previous state that React used to render the UI with. The React-level app state is ephemeral, only used for rendering it once. All renders exclusively happen in response to state updates over websockets.
The one area that I'm having difficulties with is how to structure that ephemeral state on the React side so that rendering the updated state object is as quick and efficient as possible. I'm a backend guy and have no prior experience in building a React app of this nature (I last used it four years ago in a really ad-hoc manner, passing props to deeply nested child components, with state stored all over the place). I'm not quite sure what facilities and tools to use.
For example, I could use a top-level context provider with the useReducer hook, touted by many as a "Redux replacement" (which it technically isn't). Or, I could use Redux, but does it actually add any value in this case? Or something else?
Given that the whole state is replaced as a result of every action of every user, what is the best, most efficient, least render time-requiring way of structuring the React side of things?
I would like to suggest that you do not send in the entire state of each and every user over the network instead just send in the modification and let the individual users apps perform the change handling. Once you make this change you could make use.of redux and store the states in a reducer. Also doing this will help you avoid a lot of re-renders as the object references will not change for a lot of your components,
Another thing to add here is that you can store the redux state in the localStorage when the session is terminated
FurtherMore, the one problem that you could have here is that when the user re-connects, he might not get the changes that happened while he was online.
To solve this, you can maintain a transaction id for each user so that the user is sent all the data post that transactionId till the current state by the server and then the app can process and update the transactions
Or the other approach if to completely fetch the data when the user connects for first time or reconnects.
As far as using useReducer or Redux is concerned, you need to decide that based on the complexity of your App.
Cases where the app is small might easily be covered with useReducer and useContext but if you states are complex and you need to maintain multiple reducers, you should go ahead with Redux as it provides moree flexibility with data storage
EDIT:
If the only solution for you is to send the data totally to frontend and let the frontend render it, then you need to divide your frontend code into various simpler modules as much as possible so that no component is using a a complex state.
Once you do that you can make use of shouldComponentUpdate or areEqual parameter to a class component or functional component respectively.
The idea here is to compare the previous and current value that you get from props and let go ahead with the rendering logic or not.
You can store the state as it comes to a reducer inside the redux state, that way, you would be able to implement selectors that are memoized and are able to return data which doesn't change if the actual value hasn't change.
Also while you are using connect for your React app component, its actually a functional component, so unless mapStateToProps returns a value whose reference changes, it will prevent the re-render itself since its a PureComponent
I would strongly suggest, you go through the documentation of shouldComponentUpdate, React.memo and redux. Also look into reselect library that helps you implement memoized selectors
Flux design pattern has been such help in simplifying my web application. However I ended up directly calling web APIs for certain situations simply because Flux seemed such overkill for the job. I was wondering how others might have solved such problem in a Flux way.
As the diagram suggests, we created the Action via the Action Creator for all Web API calls. I will give an example scenario. Let's say there are 3 components that are interested in User Store changes at the moment. User clicks one of them to load a list of user's hobbies from the back-end. But I only want only that one particular UI component to display the list of hobbies due to the user's action. The other 2 components won't change at all. Traditionally this would have been a simple couple lines asynch call with a callback. If you are to religiously follow Flux for this,
You create an action via Action Creator with a specific reference ID
Fetch data via Web API
Upon receiving data, action is created using the Action Creator
User store listens to this result arriving via the action
Update the store
Fire store updated event, all 3 components react to that and check if that was for mine using the reference ID
then finally render with the data fetched in that 1 UI component
My app having many small parts that load data dynamically like this per user action, I decided to use Flux for things that many components have to share states with since the stores act as centralized state provider. How do you guys use Flux to do simple data fetches such as the one mentioned above?
There are couple of ways to solve this.
Let all the components receive the update and the component decide whether to update or ignore the update.
Split up your store and subscribe only to those which are need in the component. This approach can get messy with stores getting dependent on each other and simultaneous dispatch problem.
If you haven't used any flux library , redux is highly recommended. It solves this by allowing the components to subscribe to part of state(store) tree.
I Have react app which contains many pages. For each page i added store. I using params from url for example photoId then passing to actioncreator which call service and then dispatching data to store. In page component i have store listener. Store imiting change and listener calling render for new state.
Store and action creator relates to this page only. How to create pages more simple?
Thank you!
The Flux model (using actions, dispatcher, and stores) works well for larger apps where a data fetch may affect many components and pages. If you think your app will grow then it may be worth the extra verbosity. If you're keeping your app small then composing plain React components is a great way to keep things simple and there is nothing wrong with doing it as long as you separate the data operations from the display, the way your linked example showed. Have fun!
I'm developing a web app with React + Flux. But sometimes, I am confused about where to put the data of a component.
Flux says that we should keep the data in the store. When the data changed, store should emit a change event, then the react components which listen to the store's change event should call setState with the data in the store.
But in this way, one react component is made by two parts, which are the component it self, and the store to be listened. Sometimes I want the component to be more individual. I don't want some state of this component to be related to any store, so I store the state in the component jsx file. In this way it is not a flux style, but just react.
I'm not sure if I'm doing the right thing. Should a fluxible app to be totally obey the flux or not?
There is no right answer to this question.
You could differentiate between application state and view state just as much as you could reason that all state should live in one global store.
Application state could be User information, product information or that type of data whereas view state could be related to toggling a div or what color a link should have depending on the application state.
These two approaches are both used in the wild and there is just a matter of preference.
This is a good read that argues for the case of a single state.
I won't link to the other reasoning as it's the "flux way" and an easy Google