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

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

https://github.com/react-boilerplate/react-boilerplate/

deck

By Nikhil John

deck

  • 697