Refactor with-context-api example to use functional components (#9092)
This commit is contained in:
parent
2874a3e0f1
commit
fd0ba93faa
6 changed files with 96 additions and 100 deletions
|
@ -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.
|
||||
|
|
31
examples/with-context-api/components/Counter.js
Normal file
31
examples/with-context-api/components/Counter.js
Normal 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)
|
|
@ -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 }
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue