React, Redux, Apollo and friends..
π, π, βοΈ, & π¨βπ§βπ¦
π₯ Best practices and such π₯
Dave Anderson - Stride
π£ Overview π£
- High-level thoughts and best practices π€
- Feel free to ask questions βοΈ
- Some solid references for reading, but most examples will be live-googled if needed π
π Pure Functions π
- Simple: Input -> Output
- No side effects
- No dependency to outside state
- Easy to test
- Easy to reason about
- Name it well
- Keep it small
- Decompose complex operations into more, easily testable pure functions
π React π
- Organizing
- Components
- Containers
- Pages
- Testing
React - Organization
- components/
- MyComponent.js
- AnotherComponent/
- index.js <- just a component!
- styles.js
- containers/
- MyContainer/
- index.js <- connect redux & apollo
- styles.js
- component.js <- just a component!
- MyContainer/
- pages/
- similar to components and containers..
React Components
- Prefer functional stateless components
- Pure! View only! Easy to test!
- Use class components only when React lifecycle hooks are needed
- Local state - think hard if it's needed!
- Harder to reason about and test!
- Decompose functionality into more components or functions in utility modules
Containers
- Inject Redux state and Apollo data into components
- Test view separately as a pure function of props
- Test mapping as pure functions separately too
- mapStateToProps
- mapDispatchToProps
- mapResultsToProps
Pages
- Basically components or containers but..
- Used to organize things into page/screen based views
- Useful to separate into its own folder for organization purposes
Testing
- Where to keep them? Mirror folder structure under `tests` or keep alongside tested unit of code?
- Make Unit tests! Lots of them!
- Cheap: 1600+ running in < 3 seconds
- Enzyme
- Prefer shallow over mount
- Use mount for lifecycle events or deeply nested components
- Avoid render when possible (slow)
- Ensure small components with output as a pure function of props for manageable testing scope
- Use dependency injection of props rather than globals such as `window` when possible
π Redux π
- State, reducers, selectors, actions
- Structure
- Speed bumps
Redux - State, etc.
- Store minimalΒ state required to render app
- Not state if it can be derived from another value
- Use selectors to abstract containers from shape of state
- Selectors for simple values from state
- Selectors for computed values from state
- Pure functions! Test them!
- Redux-actions to help with boilerplate for reducers and actions
Redux - Structure
- store
- user
- reducers.js
- actions.js
- selectors.js
- anotherStore
- ...
- user
Redux - Speed bumps
- Avoid connecting leaf-level components to store!
-
- Harder to reason about - prefer passing down props
- Serializing state - local storage or server session
- OR just use Apollo mutations to persist on the server!
- Normalizing API data - painful - redundant with Apollo
- Mixing Apollo cache data and redux state - not recommended
- Most redux code for managing API connections is made redundant by Apollo
βοΈ Apollo βοΈ
- Queries
- Mutations
- Testing w/ Mock API
Apollo - Queries
- Similar to redux, use `grapqhl()` per `gql` query to connect component to Apollo data/cache
- Injects `data` property to component
- Apollo handles logic for managing loading and error states
- Structure queries into fragments to understand context in which data is being used and make them more easy to reason about
- Use functional `compose` to organize Higher Order Components
- Avoid using lower level API to query the cache if possible!
- Make changes to schema to serve the client - quick feedback loops
Apollo - Mutations
- Graphql Mutations are used to change data on the server
- Also connected to component via `graphql()`
- Injects `mutation` property to component
- Call function (Promise) with arguments to resolve the change to the server
- Use name and alias options to differentiate when multiple `mutations` are present.
- Queries won't reflect changed data automatically!
- Refetch queries to reflect changed data
- Use optimistic mutation to immediately make changes to local Apollo cache without server response
Apollo - Mock API & Testing
- Graphql endpoints have a statically typed schema
- Schema can be generated through introspection on the endpoint and used by tools for things like
- API mocking
- Contract testing
βοΈ Questions βοΈ
- π?
- π?
- βοΈ?
References
- 9 Things To Learn in React..
https://camjackson.net/post/9-things-every-reactjs-beginner-should-know - Functional stateless components in React
https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc - Organizing React and Redux:
https://medium.com/bumpers/isnt-our-code-just-the-best-f028a78f33a9 - Reducing Redux code with Apollo:
https://dev-blog.apollodata.com/reducing-our-redux-code-with-react-apollo-5091b9de9c2a
More references...
- Redux Selectors:
https://www.saltycrane.com/blog/2017/05/what-are-redux-selectors-why-use-them/ - Organizing State:
https://redux.js.org/docs/faq/OrganizingState.html - Graphql Cheatsheet:
https://wehavefaces.net/graphql-shorthand-notation-cheatsheet-17cd715861b6 - Apollo Queries:
https://www.apollographql.com/docs/react/basics/queries.html - Apollo v1 Fragments & Pokemon tutorial:
https://www.learnapollo.com/tutorial-react/react-04/ - Apollo Mutations:
https://www.apollographql.com/docs/react/basics/mutations.html
React, Redux, Apollo and friends
By dvndrsn
React, Redux, Apollo and friends
Best practices for using these frameworks together
- 696