Refactor class components to functional @ examples (#13398)
**Affected examples** with-segment-analytics with-slate with-portals-ssr ( _with-portals-ssr is based on a package not being updated in the last year_) with-videojs with-next-page-transitions with-firebase-cloud-messaging with-dynamic-app-layout with-dynamic-import with-next-transition with-carbon-components with-cerebral with-custom-babel-config Here and there I have removed some redundant imports as well. I believe with this PR, there are only 1 or 2 examples left using class-based components. If by any chance you find any, let me know and I'll refactor them too. If you don't like anything or you want me to change something, please let me know. **If there is anything else you'd like me to help with, I would be honored to assist.**
This commit is contained in:
parent
dcf446d83d
commit
4a02dc5a17
15 changed files with 247 additions and 301 deletions
|
@ -1,12 +1,11 @@
|
|||
import { Component, Fragment } from 'react'
|
||||
import { Button } from 'carbon-components-react'
|
||||
|
||||
export default class DemoApp extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<Button>Hello, world!</Button>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
const Home = () => {
|
||||
return (
|
||||
<>
|
||||
<Button>Hello, world!</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
import { Component } from 'react'
|
||||
import { Controller } from 'cerebral'
|
||||
import Devtools from 'cerebral/devtools'
|
||||
import { Container } from '@cerebral/react'
|
||||
import Page from '../components/Page'
|
||||
import clock from '../modules/clock'
|
||||
|
||||
export default class Counter extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// The controller will be instantiated for every page change and we only
|
||||
// add the devtools if we indeed are running in the browser
|
||||
this.controller = Controller({
|
||||
devtools:
|
||||
process.env.NODE_ENV === 'production' || typeof window === 'undefined'
|
||||
? null
|
||||
: Devtools({ host: 'localhost:8787' }),
|
||||
modules: { clock },
|
||||
stateChanges: props.stateChanges,
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Container controller={this.controller}>
|
||||
<Page title="Index Page" linkTo="/other" />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
const Home = (props) => {
|
||||
const { stateChanges } = props
|
||||
|
||||
const controller = Controller({
|
||||
devtools:
|
||||
process.env.NODE_ENV === 'production' || typeof window === 'undefined'
|
||||
? null
|
||||
: Devtools({ host: 'localhost:8787' }),
|
||||
modules: { clock },
|
||||
stateChanges: stateChanges,
|
||||
})
|
||||
|
||||
return (
|
||||
<Container controller={controller}>
|
||||
<Page title="Index Page" linkTo="/other" />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
import { Component } from 'react'
|
||||
import { Controller } from 'cerebral'
|
||||
import Devtools from 'cerebral/devtools'
|
||||
import { Container } from '@cerebral/react'
|
||||
import Page from '../components/Page'
|
||||
import clock from '../modules/clock'
|
||||
|
||||
export default class Counter extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
// The controller will be instantiated for every page change and we only
|
||||
// add the devtools if we indeed are running in the browser
|
||||
this.controller = Controller({
|
||||
devtools:
|
||||
process.env.NODE_ENV === 'production' || typeof window === 'undefined'
|
||||
? null
|
||||
: Devtools({ host: 'localhost:8787' }),
|
||||
modules: { clock },
|
||||
stateChanges: props.stateChanges,
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Container controller={this.controller}>
|
||||
<Page title="Other Page" linkTo="/" />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
const Other = (props) => {
|
||||
const { stateChanges } = props
|
||||
|
||||
const controller = Controller({
|
||||
devtools:
|
||||
process.env.NODE_ENV === 'production' || typeof window === 'undefined'
|
||||
? null
|
||||
: Devtools({ host: 'localhost:8787' }),
|
||||
modules: { clock },
|
||||
stateChanges: stateChanges,
|
||||
})
|
||||
|
||||
return (
|
||||
<Container controller={controller}>
|
||||
<Page title="Index Page" linkTo="/other" />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Other
|
||||
|
|
|
@ -1,48 +1,37 @@
|
|||
import { Component } from 'react'
|
||||
export default class MyLuckNo extends Component {
|
||||
constructor(...args) {
|
||||
super(...args)
|
||||
this.state = { randomNo: null }
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
const MyLuckNo = () => {
|
||||
const [randomNumber, setRandomNumber] = useState(null)
|
||||
|
||||
const recalculate = () => {
|
||||
setRandomNumber(Math.ceil(Math.random() * 100))
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.recalculate()
|
||||
}
|
||||
useEffect(() => {
|
||||
recalculate()
|
||||
}, [])
|
||||
|
||||
recalculate() {
|
||||
this.setState({
|
||||
randomNo: Math.ceil(Math.random() * 100),
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { randomNo } = this.state
|
||||
|
||||
if (randomNo === null) {
|
||||
return <p>Please wait..</p>
|
||||
const message = do {
|
||||
if (randomNumber < 30) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
;('Do not give up. Try again.')
|
||||
} else if (randomNumber < 60) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
;('You are a lucky guy')
|
||||
} else {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
;('You are soooo lucky!')
|
||||
}
|
||||
|
||||
// This is an experimental JavaScript feature where we can get with
|
||||
// using babel-preset-stage-0
|
||||
const message = do {
|
||||
if (randomNo < 30) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
;('Do not give up. Try again.')
|
||||
} else if (randomNo < 60) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
;('You are a lucky guy')
|
||||
} else {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
;('You are soooo lucky!')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Your Lucky number is: "{randomNo}"</h3>
|
||||
<p>{message}</p>
|
||||
<button onClick={() => this.recalculate()}>Try Again</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (randomNumber === null) return <p>Please wait..</p>
|
||||
return (
|
||||
<div>
|
||||
<h3>Your Lucky number is: "{randomNumber}"</h3>
|
||||
<p>{message}</p>
|
||||
<button onClick={() => recalculate()}>Try Again</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyLuckNo
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
|
||||
const Noop = ({ children }) => children
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { Component } from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import { firebaseCloudMessaging } from '../utils/webPush'
|
||||
|
||||
class Index extends Component {
|
||||
componentDidMount() {
|
||||
const Index = () => {
|
||||
useEffect(() => {
|
||||
firebaseCloudMessaging.init()
|
||||
}
|
||||
render() {
|
||||
return <div>Next.js with firebase cloud messaging.</div>
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <div>Next.js with firebase cloud messaging.</div>
|
||||
}
|
||||
|
||||
export default Index
|
||||
|
|
|
@ -1,43 +1,35 @@
|
|||
import React from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Link from 'next/link'
|
||||
|
||||
class About extends React.Component {
|
||||
static pageTransitionDelayEnter = true
|
||||
const About = (props) => {
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const { pageTransitionReadyToEnter } = props
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
loaded: false,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.timeoutId = setTimeout(() => {
|
||||
this.props.pageTransitionReadyToEnter()
|
||||
this.setState({ loaded: true })
|
||||
useEffect(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
pageTransitionReadyToEnter()
|
||||
setLoaded(true)
|
||||
}, 2000)
|
||||
}
|
||||
return () => {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
}, [pageTransitionReadyToEnter])
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.timeoutId) clearTimeout(this.timeoutId)
|
||||
}
|
||||
if (!loaded) return null
|
||||
|
||||
render() {
|
||||
if (!this.state.loaded) return null
|
||||
return (
|
||||
<div className="container bg-success page">
|
||||
<h1>About us</h1>
|
||||
<p>
|
||||
Notice how a loading spinner showed up while my content was "loading"?
|
||||
Pretty neat, huh?
|
||||
</p>
|
||||
<Link href="/">
|
||||
<a className="btn btn-light">Go back home</a>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="container bg-success page">
|
||||
<h1>About us</h1>
|
||||
<p>
|
||||
Notice how a loading spinner showed up while my content was "loading"?
|
||||
Pretty neat, huh?
|
||||
</p>
|
||||
<Link href="/">
|
||||
<a className="btn btn-light">Go back home</a>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
About.propTypes = {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"dependencies": {
|
||||
"@jesstelford/react-portal-universal": "1.0.0",
|
||||
"next": "latest",
|
||||
"react": "^16.8.0",
|
||||
"react-dom": "^16.8.0"
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +1,60 @@
|
|||
import { Component } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { UniversalPortal } from '@jesstelford/react-portal-universal'
|
||||
|
||||
export default class Index extends Component {
|
||||
constructor() {
|
||||
super(...arguments)
|
||||
this.state = { opened: true }
|
||||
}
|
||||
const Index = () => {
|
||||
const [isOpen, toggle] = useState(true)
|
||||
|
||||
open = () => {
|
||||
this.setState({ opened: true })
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{/* A portal that is adjacent to its target */}
|
||||
<div id="target" />
|
||||
<UniversalPortal selector="#target">
|
||||
<h1>Hello Portal</h1>
|
||||
</UniversalPortal>
|
||||
|
||||
close = () => {
|
||||
this.setState({ opened: false })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
{/* A portal that is adjacent to its target */}
|
||||
<div id="target" />
|
||||
<UniversalPortal selector="#target">
|
||||
<h1>Hello Portal</h1>
|
||||
</UniversalPortal>
|
||||
|
||||
{/* Open a modal in a portal that is elsewhere in the react tree */}
|
||||
<button type="button" onClick={this.open}>
|
||||
Open Modal
|
||||
</button>
|
||||
{this.state.opened && (
|
||||
<UniversalPortal selector="#modal">
|
||||
{/* Open a modal in a portal that is elsewhere in the react tree */}
|
||||
<button onClick={() => toggle(!isOpen)} type="button">
|
||||
Open Modal
|
||||
</button>
|
||||
{isOpen && (
|
||||
<UniversalPortal selector="#modal">
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
backgroundColor: 'white',
|
||||
position: 'absolute',
|
||||
top: '10%',
|
||||
right: '10%',
|
||||
bottom: '10%',
|
||||
left: '10%',
|
||||
padding: '1em',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
position: 'absolute',
|
||||
top: '10%',
|
||||
right: '10%',
|
||||
bottom: '10%',
|
||||
left: '10%',
|
||||
padding: '1em',
|
||||
}}
|
||||
>
|
||||
<p>
|
||||
This modal is rendered using{' '}
|
||||
<a href="https://www.npmjs.com/package/@jesstelford/react-portal-universal">
|
||||
<code>@jesstelford/react-portal-universal</code>
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<button type="button" onClick={this.close}>
|
||||
Close Modal
|
||||
</button>
|
||||
</div>
|
||||
<p>
|
||||
This modal is rendered using{' '}
|
||||
<a href="https://www.npmjs.com/package/@jesstelford/react-portal-universal">
|
||||
<code>@jesstelford/react-portal-universal</code>
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<button type="button" onClick={() => toggle(!isOpen)}>
|
||||
Close Modal
|
||||
</button>
|
||||
</div>
|
||||
</UniversalPortal>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</UniversalPortal>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Index
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"dependencies": {
|
||||
"@segment/snippet": "^4.0.1",
|
||||
"next": "latest",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0"
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,49 +1,47 @@
|
|||
import { Component } from 'react'
|
||||
import { useState } from 'react'
|
||||
|
||||
export default class Contact extends Component {
|
||||
state = { message: '' }
|
||||
const Contact = () => {
|
||||
const [message, setMessage] = useState('')
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1>This is the Contact page</h1>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<label>
|
||||
<span>Message:</span>
|
||||
<textarea onChange={this.handleInput} value={this.state.message} />
|
||||
</label>
|
||||
<button type="submit">submit</button>
|
||||
</form>
|
||||
|
||||
<style jsx>{`
|
||||
label span {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-width: 300px;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 12px;
|
||||
display: block;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
handleInput = (e) => {
|
||||
this.setState({ message: e.target.value })
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
global.analytics.track('Form Submitted', {
|
||||
message: this.state.message,
|
||||
message,
|
||||
})
|
||||
this.setState({ message: '' })
|
||||
setMessage('')
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>This is the Contact page</h1>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label>
|
||||
<span>Message:</span>
|
||||
<textarea
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
value={message}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit">submit</button>
|
||||
</form>
|
||||
|
||||
<style jsx>{`
|
||||
label span {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-width: 300px;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 12px;
|
||||
display: block;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Contact
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
import { Component } from 'react'
|
||||
import Link from 'next/link'
|
||||
import Editor from '../components/NextEditor'
|
||||
|
||||
class MultipleEditors extends Component {
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Link href="/">
|
||||
<a>Go to Home</a>
|
||||
</Link>
|
||||
<hr />
|
||||
<Editor slateKey="foo" defaultValue="Foo" />
|
||||
<hr />
|
||||
<Editor slateKey="bar" defaultValue="Bar" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
const MultipleEditors = () => {
|
||||
return (
|
||||
<>
|
||||
<Link href="/">
|
||||
<a>Go to Home</a>
|
||||
</Link>
|
||||
<hr />
|
||||
<Editor slateKey="foo" defaultValue="Foo" />
|
||||
<hr />
|
||||
<Editor slateKey="bar" defaultValue="Bar" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default MultipleEditors
|
||||
|
|
|
@ -1,34 +1,25 @@
|
|||
import { Component } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import videojs from 'video.js'
|
||||
import 'videojs-youtube'
|
||||
|
||||
class Player extends Component {
|
||||
componentDidMount() {
|
||||
// instantiate Video.js
|
||||
this.player = videojs(this.videoNode, this.props, function onPlayerReady() {
|
||||
console.log('onPlayerReady', this)
|
||||
})
|
||||
}
|
||||
const Player = (props) => {
|
||||
const [videoEl, setVideoEl] = useState(null)
|
||||
const onVideo = useCallback((el) => {
|
||||
setVideoEl(el)
|
||||
}, [])
|
||||
|
||||
// destroy player on unmount
|
||||
componentWillUnmount() {
|
||||
if (this.player) {
|
||||
this.player.dispose()
|
||||
useEffect(() => {
|
||||
const player = videojs(videoEl, props)
|
||||
return () => {
|
||||
player.dispose()
|
||||
}
|
||||
}
|
||||
}, [props, videoEl])
|
||||
|
||||
// wrap the player in a div with a `data-vjs-player` attribute
|
||||
// so videojs won't create additional wrapper in the DOM
|
||||
// see https://github.com/videojs/video.js/pull/3856
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div data-vjs-player>
|
||||
<video ref={(node) => (this.videoNode = node)} className="video-js" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div data-vjs-player>
|
||||
<video ref={onVideo} className="video-js" playsInline />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Player
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"next": "^9.1.8-canary.11",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1",
|
||||
"video.js": "^6.7.3",
|
||||
"videojs-youtube": "^2.4.1"
|
||||
},
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
import { Component } from 'react'
|
||||
import Player from '../components/Player'
|
||||
|
||||
export default class Index extends Component {
|
||||
render() {
|
||||
const videoJsOptions = {
|
||||
techOrder: ['youtube'],
|
||||
autoplay: false,
|
||||
controls: true,
|
||||
sources: [
|
||||
{
|
||||
src: 'https://www.youtube.com/watch?v=IxQB14xVas0',
|
||||
type: 'video/youtube',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return <Player {...videoJsOptions} />
|
||||
const Index = () => {
|
||||
const videoJsOptions = {
|
||||
techOrder: ['youtube'],
|
||||
autoplay: false,
|
||||
controls: true,
|
||||
sources: [
|
||||
{
|
||||
src: 'https://www.youtube.com/watch?v=IxQB14xVas0',
|
||||
type: 'video/youtube',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
return <Player {...videoJsOptions} />
|
||||
}
|
||||
|
||||
export default Index
|
||||
|
|
Loading…
Reference in a new issue