Parting Notes,
Tips n Tricks
Nikhil John
SLIDES ARE NOT IN ORDER OF PRIORITY
CODE
REVIEWS
OFTEN
Commit
Review
- Discuss before you implement
- Keep your code reviews light
- Make logical commits
- Review <400 LoC
ANNOTATE
- Make it easy for the reviewer to understand what is being reviewed
- Add detailed descriptions for your PRs
- Leave comments on the code on GitHub
BE NICE
- Leave constructive comments & don't offend
- Everyone is nice at Fountain so ¯\_(ツ)_/¯
TRY IT OUT
- Don't limit your review to just syntax, semantics and design patterns
- Quickly test the feature to see any glaring misses (staging/local)
Use shell aliases to quickly switch branches
CONTINOUSLY
REFACTOR
ADD TODOS
FIX TODOS
The best way to learn React Hooks is to port a class component to a Functional Component
FLOW WITH
REDUX
1
- Generate components using Boilerplate
-
npm run generate
-
2
- Most operations have 3 steps
- ACTION_INIT
- ACTION_SUCCESS
- ACTION_ERROR
- Add respective Constants & Actions
export function initTestAction() {
return {
type: TEST_ACTION_INIT,
};
}
export function testActionSuccess(data) {
return {
type: TEST_ACTION_SUCCESS,
data,
};
}
export function testActionError(error) {
return {
type: TEST_ACTION_ERROR,
error,
};
}
3
- Add corresponding keys in Reducer & Set values
export const initialState = {
test: {
loading: false,
error: null,
data: null,
},
};
export const testContainerReducer = (state = initialState, action) =>
produce(state, draft => {
switch (action.type) {
case TEST_ACTION_INIT:
draft.test.loading = true;
draft.test.error = false;
break;
case TEST_ACTION_SUCCESS:
draft.test.loading = false;
draft.test.error = false;
draft.test.data = action.data;
break;
case TEST_ACTION_ERROR:
draft.test.loading = false;
draft.test.error = action.error;
// draft.test.data = null;
break;
}
});
loading | error | data | |
---|---|---|---|
INIT | true | null | null |
SUCCESS | false | null | action.data |
ERROR | false | action.error | null / existing data |
4
- Add corresponding selectors
const makeSelectTestData = () =>
createSelector(
selectTestContainerDomain,
substate => substate.test.data,
);
const makeSelectTestLoading = () =>
createSelector(
selectTestContainerDomain,
substate => substate.test.loading,
);
const makeSelectTestError = () =>
createSelector(
selectTestContainerDomain,
substate => substate.test.error,
);
5
- Add saga
- Listen to INIT action
- Make API call in Try-Catch
- On success, dispatch SUCCESS action
- On error, dispatch ERROR action
export function* fetchTestData() {
const requestURL = `/api/audiences`;
try {
const { data } = yield call(get, requestURL);
yield put(testActionSuccess(data));
} catch (err) {
yield put(testActionError(err));
yield put(
addMessageAction({
text: 'Whoops! Something went wrong. Please try again!',
}),
);
}
}
export default function* testContainerSaga() {
yield takeLatest(TEST_ACTION_INIT, fetchTestData);
}
6
- Finally add the JSX code
- Add INIT action handler as prop in mapDispatchToProps
- Add loading, error and data as props in mapStateToProps
- Initiate API call using useEffect initiate the INIT action handler
- Return Error Component when error
- Return Loading Component when loading
- Render data
/**
*
* TestContainer
*
*/
import React, { memo, useEffect } from 'react';
...
import { initTestAction } from './actions';
export function TestContainer({
loading,
error,
data: testData,
initiateDataFetch,
}) {
useInjectReducer({ key: 'testContainer', reducer });
useInjectSaga({ key: 'testContainer', saga });
useEffect(() => {
initiateDataFetch();
}, [!!testData]);
if (loading) {
return <div>LOADING.....</div>;
}
if (error) {
return <div>ERROR SCREEN/MESSAGE</div>;
}
return (
<div>
<Helmet>
<title>TestContainer</title>
<meta name="description" content="Description of TestContainer" />
</Helmet>
<FormattedMessage {...messages.header} />
<div>{testData}</div>
</div>
);
}
TestContainer.propTypes = {
initiateDataFetch: PropTypes.func.isRequired,
loading: PropTypes.bool,
error: PropTypes.bool,
data: PropTypes.string,
};
const mapStateToProps = createStructuredSelector({
loading: makeSelectTestLoading(),
error: makeSelectTestError(),
data: makeSelectTestData(),
});
function mapDispatchToProps(dispatch) {
return {
initiateDataFetch: () => dispatch(initTestAction()),
};
}
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
);
export default compose(
withConnect,
memo,
)(TestContainer);
GET TO KNOW
REACT-BOILERPLATE
deck
By Nikhil John
deck
- 710