reorganized sagas to chain necessary actions

This commit is contained in:
bill bittner 2018-02-22 15:43:26 -08:00
parent 14740341e3
commit dd510d21e7
10 changed files with 117 additions and 74 deletions

View file

@ -3,13 +3,49 @@ import { renderToString } from 'react-dom/server';
import { createStore, applyMiddleware } from 'redux';
import Reducer from '../react/reducers';
import { Provider } from 'react-redux';
import { StaticRouter, matchPath } from 'react-router-dom';
import { StaticRouter } from 'react-router-dom';
import GAListener from '../react/components/GAListener';
import App from '../react/app';
import renderFullPage from './renderFullPage';
import routes from '../react/routes';
import createSagaMiddleware from 'redux-saga';
import rootSaga from '../react/sagas';
import { call } from 'redux-saga/effects';
import { handleShowPageUri } from '../react/sagas/show_uri';
import { onHandleShowPageUri } from '../react/actions/show';
// const waitAll = (sagas) => {
// console.log('sagas', sagas);
// return function * () {
// const tasks = yield sagas.map(([saga, params]) => {
// console.log('saga to fork:', saga);
// console.log('params fork:', params);
// fork(saga, params);
// });
// console.log('tasks', tasks);
// console.log('before join');
// yield tasks.map(join);
// console.log('after join');
// };
// };
//
// const getPreloaders = (req) => {
// let preloaders = [];
// routes.some(route => {
// const match = matchPath(req.path, route);
// if (match) {
// let preloadData = route.component.preloadData;
// if (preloadData instanceof Function) {
// preloaders.push([preloadData(), mockAction(match.params)]);
// };
// };
// });
// return preloaders;
// };
const returnSagaWithParams = (saga, params) => {
return function * () {
yield call(saga, params);
};
};
module.exports = (req, res) => {
let context = {};
@ -21,48 +57,40 @@ module.exports = (req, res) => {
// create a new Redux store instance
const store = createStore(Reducer, middleware);
// run the saga middlweare
sagaMiddleware.run(rootSaga);
// get params
const action = onHandleShowPageUri(req.params);
// create saga
const saga = returnSagaWithParams(handleShowPageUri, action);
// get data as promises
const promises = [];
routes.some(route => {
const match = matchPath(req.path, route);
if (match) {
let fetchData = route.component.fetchData;
if (fetchData instanceof Function) {
promises.push(fetchData(store, match));
};
};
});
console.log('promises', promises);
// run the saga middleware
sagaMiddleware
.run(saga)
.done
.then(() => {
console.log('preload sagas are done');
// render component to a string
const html = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<GAListener>
<App />
</GAListener>
</StaticRouter>
</Provider>
);
// after promises have resolved, render the component
Promise.all(promises).then(data => {
console.log('data:', data);
// render component to a string
const html = renderToString(
<Provider store={store}>
<StaticRouter location={req.url} context={context}>
<GAListener>
<App />
</GAListener>
</StaticRouter>
</Provider>
);
// check for a redirect
if (context.url) {
console.log('REDIRECTING:', context.url);
return res.redirect(301, context.url);
} else {
console.log(`we're good, send the response`, html);
}
// check for a redirect
if (context.url) {
console.log('REDIRECTING:', context.url);
return res.redirect(301, context.url);
} else {
console.log(`we're good, send the response`, html);
}
// get the initial state from our Redux store
const preloadedState = store.getState();
// get the initial state from our Redux store
const preloadedState = store.getState();
// send the rendered page back to the client
res.send(renderFullPage(html, preloadedState));
});
// send the rendered page back to the client
res.send(renderFullPage(html, preloadedState));
});
};

View file

@ -86,6 +86,7 @@
"husky": "^0.13.4",
"mocha": "^4.0.1",
"redux-devtools": "^3.4.1",
"regenerator-transform": "^0.12.3",
"webpack": "^3.10.0"
}
}

View file

@ -3,8 +3,7 @@ import * as actions from 'constants/show_action_types';
import { CHANNEL, ASSET_LITE, ASSET_DETAILS } from 'constants/show_request_types';
// basic request parsing
export function handleShowPageUri (params) {
console.log('dispatching handleShowpageUri');
export function onHandleShowPageUri (params) {
return {
type: actions.HANDLE_SHOW_URI,
data: params,
@ -13,7 +12,7 @@ export function handleShowPageUri (params) {
export function onRequestError (error) {
return {
type: actions.REQUEST_UPDATE_ERROR,
type: actions.REQUEST_ERROR,
data: error,
};
};
@ -47,6 +46,16 @@ export function onNewAssetRequest (name, id, channelName, channelId, extension)
};
};
export function onRequestUpdate (requestType, requestId) {
return {
type: actions.REQUEST_UPDATE,
data: {
requestType,
requestId,
},
};
};
export function addRequestToRequestList (id, error, key) {
return {
type: actions.REQUEST_LIST_ADD,

View file

@ -1,6 +1,7 @@
// request actions
export const HANDLE_SHOW_URI = 'HANDLE_SHOW_URI';
export const REQUEST_UPDATE_ERROR = 'REQUEST_UPDATE_ERROR';
export const REQUEST_ERROR = 'REQUEST_ERROR';
export const REQUEST_UPDATE = 'REQUEST_UPDATE'
export const ASSET_REQUEST_NEW = 'ASSET_REQUEST_NEW';
export const CHANNEL_REQUEST_NEW = 'CHANNEL_REQUEST_NEW';
export const REQUEST_LIST_ADD = 'REQUEST_LIST_ADD';

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { handleShowPageUri } from 'actions/show';
import { onHandleShowPageUri } from 'actions/show';
import View from './view';
const mapStateToProps = ({ show }) => {
@ -10,7 +10,7 @@ const mapStateToProps = ({ show }) => {
};
const mapDispatchToProps = {
handleShowPageUri,
onHandleShowPageUri,
};
export default connect(mapStateToProps, mapDispatchToProps)(View);

View file

@ -3,28 +3,23 @@ import ErrorPage from 'components/ErrorPage';
import ShowAssetLite from 'components/ShowAssetLite';
import ShowAssetDetails from 'components/ShowAssetDetails';
import ShowChannel from 'components/ShowChannel';
import { handleShowPageUri } from 'actions/show';
import { CHANNEL, ASSET_LITE, ASSET_DETAILS } from 'constants/show_request_types';
class ShowPage extends React.Component {
static fetchData (store, match) {
console.log('the store:', store);
return store.dispatch(handleShowPageUri(match.params));
}
componentDidMount () {
this.props.handleShowPageUri(this.props.match.params);
this.props.onHandleShowPageUri(this.props.match.params);
}
componentWillReceiveProps (nextProps) {
if (nextProps.match.params !== this.props.match.params) {
this.props.handleShowPageUri(nextProps.match.params);
this.props.onHandleShowPageUri(nextProps.match.params);
}
}
render () {
const { error, requestType } = this.props;
if (error) {
return (
<ErrorPage error={error}/>
<ErrorPage error={error} />
);
}
switch (requestType) {

View file

@ -19,14 +19,14 @@ const initialState = {
export default function (state = initialState, action) {
switch (action.type) {
// handle request
case actions.REQUEST_UPDATE_ERROR:
case actions.REQUEST_ERROR:
return Object.assign({}, state, {
request: Object.assign({}, state.request, {
error: action.data,
}),
});
case actions.CHANNEL_REQUEST_NEW:
case actions.ASSET_REQUEST_NEW:
case actions.REQUEST_UPDATE:
console.log('REQUEST UPDATE');
return Object.assign({}, state, {
request: Object.assign({}, state.request, {
type: action.data.requestType,

View file

@ -1,14 +1,16 @@
import { call, put, select, takeLatest } from 'redux-saga/effects';
import * as actions from 'constants/show_action_types';
import { addRequestToRequestList, onRequestError, addAssetToAssetList } from 'actions/show';
import { addRequestToRequestList, onRequestError, onRequestUpdate, addAssetToAssetList } from 'actions/show';
import { getLongClaimId, getShortId, getClaimData } from 'api/assetApi';
import { selectShowState } from 'selectors/show';
function * newAssetRequest (action) {
const { requestId, name, modifier } = action.data;
const state = yield select(selectShowState);
export function * newAssetRequest (action) {
const { requestType, requestId, name, modifier } = action.data;
// put an action to update the request in redux
yield put(onRequestUpdate(requestType, requestId));
// is this an existing request?
// If this uri is in the request list, it's already been fetched
const state = yield select(selectShowState);
if (state.requestList[requestId]) {
console.log('that request already exists in the request list!');
return null;

View file

@ -1,14 +1,16 @@
import {call, put, select, takeLatest} from 'redux-saga/effects';
import * as actions from 'constants/show_action_types';
import { addNewChannelToChannelList, addRequestToRequestList, onRequestError, updateChannelClaims } from 'actions/show';
import { addNewChannelToChannelList, addRequestToRequestList, onRequestError, onRequestUpdate, updateChannelClaims } from 'actions/show';
import { getChannelClaims, getChannelData } from 'api/channelApi';
import { selectShowState } from 'selectors/show';
function * getNewChannelAndUpdateChannelList (action) {
const { requestId, channelName, channelId } = action.data;
const state = yield select(selectShowState);
export function * newChannelRequest (action) {
const { requestType, requestId, channelName, channelId } = action.data;
// put an action to update the request in redux
yield put(onRequestUpdate(requestType, requestId));
// is this an existing request?
// If this uri is in the request list, it's already been fetched
const state = yield select(selectShowState);
if (state.requestList[requestId]) {
console.log('that request already exists in the request list!');
return null;
@ -45,7 +47,7 @@ function * getNewChannelAndUpdateChannelList (action) {
}
export function * watchNewChannelRequest () {
yield takeLatest(actions.CHANNEL_REQUEST_NEW, getNewChannelAndUpdateChannelList);
yield takeLatest(actions.CHANNEL_REQUEST_NEW, newChannelRequest);
};
function * getNewClaimsAndUpdateChannel (action) {

View file

@ -1,10 +1,14 @@
import { call, put, takeLatest } from 'redux-saga/effects';
import * as actions from 'constants/show_action_types';
import { onRequestError, onNewChannelRequest, onNewAssetRequest } from 'actions/show';
import { newAssetRequest } from 'sagas/show_asset';
import { newChannelRequest } from 'sagas/show_channel';
import lbryUri from 'utils/lbryUri';
function * parseAndUpdateIdentifierAndClaim (modifier, claim) {
console.log('parseAndUpdateIdentifierAndClaim');
console.log('modifier:', modifier);
console.log('claim:', claim);
// this is a request for an asset
// claim will be an asset claim
// the identifier could be a channel or a claim id
@ -17,9 +21,9 @@ function * parseAndUpdateIdentifierAndClaim (modifier, claim) {
}
// trigger an new action to update the store
if (isChannel) {
return yield put(onNewAssetRequest(claimName, null, channelName, channelClaimId, extension));
return yield call(newAssetRequest, onNewAssetRequest(claimName, null, channelName, channelClaimId, extension));
};
yield put(onNewAssetRequest(claimName, claimId, null, null, extension));
yield call(newAssetRequest, onNewAssetRequest(claimName, claimId, null, null, extension));
}
function * parseAndUpdateClaimOnly (claim) {
console.log('parseAndUpdateIdentifierAndClaim');
@ -34,7 +38,7 @@ function * parseAndUpdateClaimOnly (claim) {
// trigger an new action to update the store
// return early if this request is for a channel
if (isChannel) {
return yield put(onNewChannelRequest(channelName, channelClaimId));
return yield call(newChannelRequest, onNewChannelRequest(channelName, channelClaimId));
}
// if not for a channel, parse the claim request
let claimName, extension;
@ -43,11 +47,12 @@ function * parseAndUpdateClaimOnly (claim) {
} catch (error) {
return yield put(onRequestError(error.message));
}
yield put(onNewAssetRequest(claimName, null, null, null, extension));
yield call(newAssetRequest, onNewAssetRequest(claimName, null, null, null, extension));
}
function * handleShowPageUri (action) {
export function * handleShowPageUri (action) {
console.log('handleShowPageUri');
console.log('action:', action);
const { identifier, claim } = action.data;
if (identifier) {
return yield call(parseAndUpdateIdentifierAndClaim, identifier, claim);