Skip to content

Instantly share code, notes, and snippets.

@sergeysova
Last active February 23, 2019 17:15
Show Gist options
  • Save sergeysova/6c7961b7de63c7c0d51aac0acf80c404 to your computer and use it in GitHub Desktop.
Save sergeysova/6c7961b7de63c7c0d51aac0acf80c404 to your computer and use it in GitHub Desktop.
import { fetchStatus } from "@lib/fetch";
import { userApi } from "@feature/users/api";
import { actions } from "./symbiotes";
import * as selectors from "./selectors";
/*
userApi.fetchUser() should throw an Error, if server returned object with error
*/
/*
Store of users, should be mapping of userId -> User
Example: users: { 1: { id: 1, username: 'foo' } }
For usernames we can have another mapping for username -> userId
Example: usernames: { 'foo': 1 }
actions.setUser(user) should set users[user.id] = user
also it should set usernames[user.username] = user.id
*/
/*
const getUsers = createSelector(
getRootOfUsers,
(root) => root.users
)
To select user by id, use selector with props
const getUserById = createSelector(
[getUsers, (state, props) => props.userId],
(users, userId) => users[userId]
)
getUserById(getState(), { userId: 1 })
To select by username
const getUserByUsername = createSelectors(
[
getUsers,
getUsernames,
(state, props) => props.username,
],
(users, usernames, username) => usernames[username] && users[usernames[username]]
)
getUserByUsername(getState(), { username: 'foo' })
*/
/**
* Fetch is just a loading from the API
*/
const fetchUser = (username) => (dispatch) =>
dispatch(userApi.fetchUser(username))
.then((user) => ({ lastUpdate: Date.now(), ...user }))
/**
* Load is a fetch and set to the store
*/
const loadUser = (username) => async (dispatch) => {
const user = dispatch(fetchUser(username))
dispatch(actions.setUser(user));
return user
}
const TIMEOUT_TO_UPDATE_USER = 3000 // ms
const isUserNeedUpdate = (user) => Date.now() - user.lastUpdate > TIMEOUT_TO_UPDATE_USER;
export const loadOrUpdateUser = (username) => async (dispatch, getState) => {
dispatch(actions.setFetchStatus(fetchStatus.loading));
dispatch(actions.resetError());
let user = getUserByUsername(getState(), { username });
const isUserShouldBeLoaded = !user || isUserNeedUpdate(user)
if (isUserShouldBeLoaded) {
try {
user = await dispatch(fetchUser(username));
dispatch(actions.setFetchStatus(fetchStatus.finished));
}
catch (error) {
dispatch(actions.setError(error.message));
dispatch(actions.setFetchStatus(fetchStatus.failed));
}
}
dispatch(actions.setCurrentUser(user));
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment