Refactor with-context-api example to use functional components (#9092)

This commit is contained in:
Henrik Wenz 2019-10-18 08:00:23 +02:00 committed by Joe Haddad
parent 2874a3e0f1
commit fd0ba93faa
6 changed files with 96 additions and 100 deletions

View file

@ -43,8 +43,8 @@ This example shows how to use react context api in our app.
It provides an example of using `pages/_app.js` to include the context api provider and then shows how both the `pages/index.js` and `pages/about.js` can both share the same data using the context api consumer.
We start of by creating two contexts. One that actually never changes (`CounterDispatchContext`) and one that changes more often (`CounterStateContext`).
The `pages/index.js` shows how to, from the home page, increment and decrement the context data by 1 (a hard code value in the context provider itself).
The `pages/about.js` shows how to, from the about page, how to pass an increment value from the about page into the context provider itself.
\*_Based on WesBos example_.
The `pages/about.js` shows how to pass an increment value from the about page into the context provider itself.

View file

@ -0,0 +1,31 @@
import React, { useReducer, useContext } from 'react'
const CounterStateContext = React.createContext()
const CounterDispatchContext = React.createContext()
const reducer = (state, action) => {
switch (action.type) {
case 'INCREASE':
return state + 1
case 'DECREASE':
return state - 1
case 'INCREASE_BY':
return state + action.payload
default:
throw new Error(`Unkown action: ${action.type}`)
}
}
export const CounterProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, 0)
return (
<CounterDispatchContext.Provider value={dispatch}>
<CounterStateContext.Provider value={state}>
{children}
</CounterStateContext.Provider>
</CounterDispatchContext.Provider>
)
}
export const useCount = () => useContext(CounterStateContext)
export const useDispatchCount = () => useContext(CounterDispatchContext)

View file

@ -1,40 +0,0 @@
import React, { Component } from 'react'
/* First we will make a new context */
const CounterContext = React.createContext()
/* Then create a provider Component */
class CounterProvider extends Component {
state = {
count: 0,
increase: () => {
this.setState((state, props) => ({
count: state.count + 1
}))
},
increaseBy: val => {
this.setState((state, props) => ({
count: state.count + val
}))
},
decrease: () => {
this.setState((state, props) => ({
count: state.count - 1
}))
}
}
render () {
return (
<CounterContext.Provider value={this.state}>
{this.props.children}
</CounterContext.Provider>
)
}
}
/* then make a consumer which will surface it */
const CounterConsumer = CounterContext.Consumer
export default CounterProvider
export { CounterConsumer }

View file

@ -1,12 +1,10 @@
import App from 'next/app'
/* First we import our provider */
import CounterProvider from '../components/CounterProvider'
import { CounterProvider } from '../components/Counter'
class MyApp extends App {
render () {
const { Component, pageProps } = this.props
return (
/* Then we wrap our components with the provider */
<CounterProvider>
<Component {...pageProps} />
</CounterProvider>

View file

@ -1,33 +1,34 @@
import React, { Component } from 'react'
/* First we import the consumer */
import { CounterConsumer } from '../components/CounterProvider'
import React from 'react'
import Link from 'next/link'
import { useCount, useDispatchCount } from '../components/Counter'
const AboutPage = () => {
const count = useCount()
const dispatch = useDispatchCount()
const handleIncrease = event =>
dispatch({
type: 'INCREASE'
})
const handleIncrease15 = event =>
dispatch({
type: 'INCREASE_BY',
payload: 15
})
export default class about extends Component {
render () {
return (
/* Then we use our context through render props */
<CounterConsumer>
{({ count, increase, increaseBy }) => (
<div>
<>
<h1>ABOUT</h1>
<p>Counter: {count}</p>
<button onClick={increase}>Increase</button>
<button
onClick={() => {
increaseBy(15)
}}
>
Increase By 15
</button>
<button onClick={handleIncrease}>Increase</button>
<button onClick={handleIncrease15}>Increase By 15</button>
<p>
<Link href='/'>
<a>Home</a>
</Link>
</p>
</div>
)}
</CounterConsumer>
</>
)
}
}
export default AboutPage

View file

@ -1,27 +1,33 @@
import React, { Component } from 'react'
import React from 'react'
import Link from 'next/link'
/* First we import the consumer */
import { CounterConsumer } from '../components/CounterProvider'
import { useCount, useDispatchCount } from '../components/Counter'
const IndexPage = () => {
const count = useCount()
const dispatch = useDispatchCount()
const handleIncrease = event =>
dispatch({
type: 'INCREASE'
})
const handleDecrease = event =>
dispatch({
type: 'DECREASE'
})
export default class index extends Component {
render () {
return (
/* Then we use our context through render props */
<CounterConsumer>
{({ count, increase, decrease }) => (
<div>
<>
<h1>HOME</h1>
<p>Counter: {count}</p>
<button onClick={increase}>Increase</button>
<button onClick={decrease}>Decrease</button>
<button onClick={handleIncrease}>Increase</button>
<button onClick={handleDecrease}>Decrease</button>
<p>
<Link href='/about'>
<a>About</a>
</Link>
</p>
</div>
)}
</CounterConsumer>
</>
)
}
}
export default IndexPage