npm install
# Start webpack-dev-server for development or viewing the examples
npm start
# Make minified build and serve that
npm run serve
# Run tests
npm test
# Run tests on file change
npm run test:watch
# Lint code
npm run lint
# Create a minified build
npm run build
Each folder contains an example or an exercise. There are no dependencies between the separate folders. Webpack is used for transpilation of the files. There is intentionally no livereload of hot module replacement to make the code easy to read. However when npm start
is running, only a page refresh is needed to see file changes.
Hello world:
- http://localhost:8080/es5-nojsx-examples/helloworld.html
- http://jsbin.com/vugafa/edit?html,js,output
Timer:
Shows that React can be used without any tooling like JS transpilation. The example itself can be opened without using NodeJS or npm. Open either ./es5-nojsx-examples/helloworld.html or ./es5-nojsx-examples/timer.html in a browser.
helloworld.html
show the basics of creating a React component and has a loop. timer.html
show a React component which uses state.
Hello world:
Timer:
Same examples as above using ES6 transpilation and JSX. It shows that React components can be written down much more concise and readable in JSX with ES6 compares to in plain ES5.
Exercise to work with enzyme and shallow rendering.
- Implement the tests in ./es6-jsx-examples/helloworld/tests/HelloWorldSpec.js
- ./es6-jsx-examples/timer/tests/TimerSpec.js can be used for inspiration
- chai-enzyme can also be used to make readable assertions
http://localhost:8080/jsx-exercise/example-page.html
Exercise to get familiar with building React components using JSX. The goal is to reproduce the page shown here. The data structure for the contents of the page can be found in ./jsx-exercise/data.js. The exercise has the following steps:
- Identify the components the exercise page consists of
- Build the components in the folder ./jsx-exercise/example-page/
- Put each component in a separate file
- Use the data structure in ./jsx-exercise/data.js
- Enable
eslint
in your editor for fast feedback on possible errors - Build the components using the stateless function notation
- After you build some components manually you can use http://magic.reactjs.net/htmltojsx.htm
- Add propType constraints
http://localhost:8080/react-form/react-form.html
Exercise to work with stateful components in React. The state of the component is displayed on the page to make debugging easier.
- Add form elements with name and value attributes to ./react-form/react-form/ReactFormPage.js
- Add a name input and a gender input
- Consider using a select input or a radio button
- Add change handlers which call
setState
to the component. NOTE: make sure thatthis
in the change handler point to the instance of the component. - Connect the change handlers to the form element
http://localhost:8080/react-giphy-search/giphy-search.html
Exercise to make an ajax call from React. The view and components are already available. The file to edit is ./react-giphy-search/giphy-search/GiphySearchPage.js.
- Make sure the value of the searchTerm input box is part of the component state
- Implement an
onSubmit
handler which callspreventDefault
- Load the data from the
onSubmit
handler:
- Call
searchGiphy
which is located in ./react-giphy-search/giphy-search/giphy-search-service.js to fetch a list of giphy's searchGiphy
returns a promise of the response of the backend. Inspect/log the data to determine how to use it.- If fetching the data fails the promise will be rejected with an
Error
instance - Use the
message
field in the state to display possible errors - Call
setState
in thethen
callback of the promise
Shows that reducers are easy to test because they are plain JS functions
- Implement the tests that are not implemented in ./testing-reducers/tests/product-reducer-spec.js
- The action creators can be used in this test as well. This ensures when the action creators are updated the tests won't break. This also means that we are testing the action creators and the reducer in the same unit test. Note the action creator for this test are simple, if they were not simple it is best to test action creators and reducers separately.
http://localhost:8080/connect-redux-to-react/connect-redux-to-react.html
A redux store has been defined which will update its state with a random giphy. The goal is to connect this store to the provided view.
- Use the redux devtools extension to inspect the updating store
- Connect redux to the app in ./connect-redux-to-react/app/App.js and ./connect-redux-to-react/random-image/RandomImagePage.js
http://localhost:8080/simple-redux-form/simple-redux-form.html
- Implement the store in ./simple-redux-from/app/store.js
- Implement the actions in ./simple-redux-from/simple-form/simple-form-actions.js NOTE you can use the spec in ./simple-redux-form/simple-form/tests/simple-form-reducer-spec.js
http://localhost:8080/redux-giphy-search/giphy-search.html
Implement an async action creator to search for giphy's.
- Implement
submitSearch
in ./redux-giphy-search/giphy-search/giphy-search-actions.js
- It should immediately send a
SUBMIT_SEARCH
event - On a successful result send a
GIPHY_RESPONSE
event - On a failure response send a
GIPHY_ERROR
event
The goal of this exercise is to lean how to make asynchronous tests. It will also become clear that when a test is async it will be difficult to write.
- Implement the empty tests in ./redux-giphy-search/giphy-search/tests/giphy-search-actions-spec.js
- Use a
done
callback of mocha when the test is async - Use the provided
assertDispatchCall
to perform assertions on the n-th call of dispatch assertDispatchCall
returns adispatchMock
Reselect enables high performing calculated properties in redux. In this exercise we are going to calculate the total payload size of the giphy's shown in the giphy search exercise.
- Create a getGiphyList select to get the giphyList out of the state
- Can use plain JS
- Create a getTotalGiphyPayloadSize which calculates the total payload size from the giphyList
- Uses
createSelector
- Use this size:
giphy.images.original.mp4_size
- Consider using
map
andreduce
- Consider writing a unit test to develop the selector
- Integrate
getTotalGiphyPayloadSize
inmapStateToProps
in ./redux-giphy-search/giphy-search/GiphySearchPage.js - Add the total payload total to the view
- Add
propType
validation for the new property