Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(introduction): add "Quick Start" page #3651

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 200 additions & 0 deletions docs/introduction/QuickStart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
---
id: quick-start
title: Quick Start
sidebar_label: Quick Start
hide_title: true
---

# Quick Start

To bootstrap your next Redux project, here are some minimal examples to get you started (_copy -> paste -> tweak_).

## Installation

All of our examples will be using the official Redux package and the **[Redux Toolkit](https://redux-toolkit.js.org/)** addon package, so let's go ahead and install those.

```bash
# NPM
npm install --save redux @reduxjs/toolkit

# Yarn
yarn add redux @reduxjs/toolkit
```

## The Redux Code

Let's say we're building a _simple_ calculator. The calculator will be able to add or subtract numbers based on the user's input.

First off, let's start by creating the actions necessary for this calculator to work. We'll need to be able to add and substract a value.

### The Actions

```js
const add = createAction('ADD')
const substract = createAction('SUBSTRACT')
```

Here we're using Redux Toolkit's `createAction` to create the necessary actions we'll be using for the app.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to elaborate a bit more on why we define actions.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also link to RTK's createAction docs.


Cool, now let's move onto the reducer.

### The Reducer

```js
const calculator = createReducer(0, {
[add]: (state, action) => state + action.payload,
[subtract]: (state, action) => state - action.payload
})
```

At first glance this may be a little strange to look at, but let's unpack it:

- The first argument passed into `createReducer` is the initial state, which we'll start at `0`.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createReducer should link to RTK's docs.

- The second argument defines a "lookup table" object, where the key is the action type and the value is the reducer function associated with the action.
- In case you aren't familiar with the weird `[add]` syntax, it is known as the [ES6 object "computed property" syntax](https://javascript.info/object#computed-properties). This allows us to create keys from actions made with `createAction` with ease (since the computed properties ultimately calls `toString()` on those variables, which `createAction` objects overrides with the value of its type property).

The reducers' implementations should be fairly straightforward, simply adding or subtracting the action payload.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is making an unfair assumption on the reader's knowledge, consider revising the wording here.


### The Slice

Now this may leave you wondering "gee, why do I need to define action creators outside of the reducer? What if there was a way to bake action creators into the reducer itself?"

Well, that's where `createSlice` from Redux Toolkit comes in :)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should link to RTK's createSlice docs.


```js
// before
const add = createAction('ADD')
const substract = createAction('SUBSTRACT')

const calculator = createReducer(0, {
[add]: (state, action) => state + action.payload,
[subtract]: (state, action) => state - action.payload
})

// after
const calculatorSlice = createSlice({
name: 'calculator',
initialState: 0,
reducers: {
add: (state, action) => state + action.payload,
subtract: (state, action) => state - action.payload
}
})
```

Now the `add` and `subtract` actions will be available via `calculatorSlice.actions` and the reducer function will be available via `calculatorSlice.reducer`. This keeps our "slice" of the store all in one place, so that we'll know where all of the logic for this part of the store resides.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should link to external resource on the concept of "slices" of stores.


Awesome, let's move onto setting up the store.

### The Store

```js
const store = configureStore({
reducer: calculatorSlice.reducer
})
```

Using Redux Toolkit's `configureStore`, we can setup the store with helpful default middleware out of the box. Unfortunately, this example won't be able to highlight this middleware, but be sure to check out the [included default middleware](https://redux-starter-kit.js.org/api/getDefaultMiddleware#included-default-middleware) to learn more about them.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should link to RTK's configureStore docs.


To Recap, here's the full code that we've written so far:

```js
const calculatorSlice = createSlice({
name: 'calculator',
initialState: 0,
reducers: {
add: (state, action) => state + action.payload,
subtract: (state, action) => state - action.payload
}
})

const store = configureStore({
reducer: calculatorSlice.reducer
})
```

Not too bad :)

## Vanilla Example

Great! Now that we have the redux portion of the code done, let's move onto creating an application that can utilize it.

```js
const valueEl = document.getElementById('value')

const render = function() {
valueEl.innerHTML = store.getState().toString()
}

// we'll need to render it once to populate the value element with some data
render()

// Setup the subscription to the value element
store.subscribe(render)

// let's destructure the actions from the calculator slice
const { add, subtract } = calculatorSlice.actions

// Setup event listeners for the buttons
document.getElementById('add').addEventListener('click', function() {
const value = document.getElementById('input').value
store.dispatch(add(value))
})

document.getElementById('subtract').addEventListener('click', function() {
const value = document.getElementById('input').value
store.dispatch(subtract(value))
})
```

alright, now we have a simple app setup that utilizes our Redux code to have a functioning calculator app. it will now dispatch actions to update the value in the store,
depending on which button was clicked.
Comment on lines +150 to +151
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes feel like I'm wanting more out of this explanation. Adding external resources might help? Or just a more in-depth explanation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs a runnable CodeSandbox here.


## React Example

Now let's take a look at the same code, but built in React. We'll need to use the `react-redux` package for the official React bindings of the Redux store.

We'll also be using the new React Redux hooks API, so be sure to check that out if you haven't already.

```jsx
const Value = function() {
const value = useSelector(state => state)

return <span>{value}</span>
}

const Button = function(props) {
const { action, children } = props
const dispatch = useDispatch()

return <button onClick={() => dispatch(action)}>{children}</button>
}

const App = function() {
const [input, setInput] = useState(0)

const handleChange = function(e) {
const { value } = e.target
setInput(Number(value))
}

return (
<Provider store={store}>
The value is <Value />
<input onChange={handleChange} />
<Button action={add(input)}>Add Amount</Button>
<Button action={subtract(input)}>Subtract Amount</Button>
Comment on lines +185 to +186
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks bad, I'm not sure why. It almost makes this code snippet unusable, since if I'm an end user copy/pasting this code I would most likely re-write this portion entirely.

</Provider>
)
}

render(<App />, document.getElementById('app'))
```

Okay so there's quite a lot to unpack here:

- First off, for the `Value` component we use the `useSelector` hook to get the piece of state from the store to display it.
- For the `Button` component, we use the `useDispatch` hook in order to dispatch the passed in actions.
- For the `App` component, we define the input element and its state here so that we can pass down the `value` of the input element to the `Button` components for dispatch. This allows the user to enter in a specified value to either add or subtract.

Great! Now we have a fully-functioning simple React calculator app :)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link to external resources and runnable CodeSandbox example.

1 change: 1 addition & 0 deletions website/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"docs": {
"Introduction": [
"introduction/getting-started",
"introduction/quick-start",
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally not a fan of this placement. The first section out of this page is about installation, but the next page this navigates to is the Installation page?

"introduction/installation",
"introduction/motivation",
"introduction/core-concepts",
Expand Down