SlideShare a Scribd company logo
1 of 34
Download to read offline
React, The Inglorious Way
Matteo Antony Mistretta
Inglorious Coderz
@antonymistretta
Why
React is evolving rapidly
A few rules, lots of strategies
Learning them makes us better coders
antony@ingloriouscoderz ~> whoami
Agenda
Class Components
Container/Presentational
Higher-Order Components
Render Props
Hooks
42
-1 +1
class Counter extends Component {
constructor(props) {
super(props)
this.state = { count: props.initialCount }
this.increment = this.increment.bind(this)
}
increment() {
this.setState({ count: this.state.count + 1 })
}
decrement() {
this.setState({ count: this.state.count - 1 })
}
render() {
const { count } = this.state
return (
<div>
<h1>{count}</h1>
<div className="input-group">
<button onClick={this.decrement.bind(this)}>-1</button>
<input
type="number"
value={count}
onChange={event => {
this.setState({ count: parseInt(event.target.value) })
}}
/>
<button onClick={this.increment}>+1</button>
</div>
</div>
)
}
}
render(<Counter initialCount={42} />)
42
42
-1 +1
class Counter extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
const { count } = this.state
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={this.decrement}>-1</button>
<input type="number" value={count} onChange={this.handleChange} />
<button onClick={this.increment}>+1</button>
</div>
</>
)
}
}
render(<Counter initialCount={42} />)
42
Agenda
Class Components
Container/Presentational
Higher-Order Components
Render Props
Hooks
42
-1 +1
class Counter extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
const { count } = this.state
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={this.decrement}>-1</button>
<input type="number" value={count} onChange={this.handleChange} />
<button onClick={this.increment}>+1</button>
</div>
</>
)
}
}
render(<Counter initialCount={42} />)
42
42
-1 +1
class CounterContainer extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
return (
<Counter
count={this.state.count}
increment={this.increment}
decrement={this.decrement}
handleChange={this.handleChange}
/>
)
}
}
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<CounterContainer initialCount={42} />)
42
42
-1 +1
class CounterContainer extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
// NOTE: this is bad
return Counter({
count: this.state.count,
increment: this.increment,
decrement: this.decrement,
handleChange: this.handleChange,
})
}
}
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<CounterContainer initialCount={42} />)
42
Agenda
Class Components
Container/Presentational
Higher-Order Components
Render Props
Hooks
42
-1 +1
class CounterContainer extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
return (
<Counter
count={this.state.count}
increment={this.increment}
decrement={this.decrement}
handleChange={this.handleChange}
/>
)
}
}
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<CounterContainer initialCount={42} />)
42
42
-1 +1
const withCounter = Enhanced =>
class CounterContainer extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
return (
<Enhanced
count={this.state.count}
increment={this.increment}
decrement={this.decrement}
handleChange={this.handleChange}
/>
)
}
}
Counter = withCounter(Counter)
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<Counter initialCount={42} />)
42
42
-1 +1
const enhance = compose(
withState('count', 'setCount', ({ initialCount }) => initialCount),
withHandlers({
increment: ({ setCount }) => () => setCount(count => count + 1),
decrement: ({ setCount }) => () => setCount(count => count - 1),
handleChange: ({ setCount }) => event =>
setCount(parseInt(event.target.value)),
}),
pure,
)
Counter = enhance(Counter)
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<Counter initialCount={42} />)
42
Agenda
Class Components
Container/Presentational
Higher-Order Components
Render Props
Hooks
Hello world!
function Parent() {
return (
<Wrapper>
<Child who="world" />
</Wrapper>
)
}
function Child({ who }) {
return `Hello ${who}!`
}
function Wrapper({ children }) {
return <h1>{children}</h1>
}
render(Parent)
Hello
WORLD!
function Parent() {
return <Wrapper who="world" Component={Child} />
}
function Child({ who }) {
return `Hello ${who}!`
}
function Wrapper({ who, Component }) {
const shoutedWho = who.toUpperCase()
return (
<h1>
<Component who={shoutedWho} />
</h1>
)
}
render(Parent)
Hello
WORLDz!
function Parent() {
return <Wrapper who="world" render={who => <Child who={who + 'z'} />} />
}
function Child({ who }) {
return `Hello ${who}!`
}
function Wrapper({ who, render }) {
const shoutedWho = who.toUpperCase()
return <h1>{render(shoutedWho)}</h1>
}
render(Parent)
Hello
WORLDz!
function Parent() {
return <Wrapper who="world">{who => <Child who={who + 'z'} />}</Wrapper>
}
function Child({ who }) {
return `Hello ${who}!`
}
function Wrapper({ children, who }) {
const shoutedWho = who.toUpperCase()
return <h1>{children(shoutedWho)}</h1>
}
render(Parent)
42
-1 +1
class CounterContainer extends PureComponent {
state = { count: this.props.initialCount }
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
render() {
return (
<Counter
count={this.state.count}
increment={this.increment}
decrement={this.decrement}
handleChange={this.handleChange}
/>
)
}
}
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<CounterContainer initialCount={42} />)
42
42
-1 +1
class CounterContainer extends PureComponent {
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
state = {
count: this.props.initialCount,
increment: this.increment,
decrement: this.decrement,
handleChange: this.handleChange,
}
render() {
return this.props.children(this.state)
}
}
function Counter({ initialCount }) {
return (
<CounterContainer initialCount={initialCount}>
{({ count, increment, decrement, handleChange }) => (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)}
</CounterContainer>
)
}
render(<Counter initialCount={42} />)
42
42
-1 +1
class CounterContainer extends PureComponent {
increment = () => this.setState(({ count }) => ({ count: count + 1 }))
decrement = () => this.setState(({ count }) => ({ count: count - 1 }))
setCount = count => this.setState({ count })
handleChange = event => this.setCount(parseInt(event.target.value))
state = {
count: this.props.initialCount,
increment: this.increment,
decrement: this.decrement,
handleChange: this.handleChange,
}
render() {
return this.props.children(this.state)
}
}
class Counter extends PureComponent {
renderCounter = ({ count, increment, decrement, handleChange }) => (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
render() {
return (
<CounterContainer initialCount={this.props.initialCount}>
{this.renderCounter}
</CounterContainer>
)
}
}
render(<Counter initialCount={42} />)
42
Agenda
Class Components
Container/Presentational
Higher-Order Components
Render Props
Hooks
They separate stateful logic
They are composable functions
They allow us to go fully functional
They keep our component hierarchy flat
42
-1 +1
const enhance = compose(
withState('count', 'setCount', ({ initialCount }) => initialCount),
withHandlers({
increment: ({ setCount }) => () => setCount(count => count + 1),
decrement: ({ setCount }) => () => setCount(count => count - 1),
handleChange: ({ setCount }) => event =>
setCount(parseInt(event.target.value)),
}),
pure,
)
Counter = enhance(Counter)
function Counter({ count, increment, decrement, handleChange }) {
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<Counter initialCount={42} />)
42
42
-1 +1
function useCounter(initialCount) {
const [count, setCount] = useState(initialCount)
const increment = () => setCount(count + 1)
const decrement = () => setCount(count - 1)
const handleChange = event => setCount(parseInt(event.target.value))
return { count, increment, decrement, handleChange }
}
Counter = memo(Counter)
function Counter({ initialCount }) {
const { count, increment, decrement, handleChange } = useCounter(initialCount)
return (
<>
<h1>{count}</h1>
<div className="input-group">
<button onClick={decrement}>-1</button>
<input type="number" value={count} onChange={handleChange} />
<button onClick={increment}>+1</button>
</div>
</>
)
}
render(<Counter initialCount={42} />)
42
Which to use?
Hello
WORLD!
function Hello({ who }) {
return <h1>{`Hello ${who}!`}</h1>
}
const enhance = Enhanced => ({ who, ...props }) => {
if (!who.length) return 'Name too short'
const shoutedWho = who.toUpperCase()
return <Enhanced {...props} who={shoutedWho} />
}
Hello = enhance(Hello)
render(<Hello who="world" />)
world
though
ly
tual
issey
const SimpleList = ({ whos }) => (
<ul style={styles.list}>
{whos.map(who => (
<li>{who}</li>
))}
</ul>
)
const ComplexList = ({ renderEven, renderOdd, whos }) => (
<ul style={styles.list}>
{whos.map((who, index) => (index % 2 ? renderEven(who) : renderOdd(who)))}
</ul>
)
const Parent = ({ whos, simple }) => {
if (simple) return <SimpleList whos={whos} />
return (
<ComplexList
renderEven={who => <li style={styles.even}>{'Even ' + who}</li>}
renderOdd={who => <li style={styles.odd}>{'Odd ' + who}</li>}
whos={whos}
/>
)
}
render(
<Parent whos={['world', 'though', 'ly', 'tual', 'issey']} simple={true} />,
)
const styles = {
list: { textAlign: 'left' },
odd: { color: 'grey' },
even: { color: 'cornflowerblue' },
}
Which to use?
Classes: getSnapshotBeforeUpdate / componentDidCatch
HOCs: proxy / before render (change props, prevent renders)
Render Props: mix logic / multiple sub-items / switch behavior
Hooks: everything else
Thank you.
Questions?
html | pdf | source

More Related Content

Similar to Matteo Antony Mistretta - React, the Inglorious way - Codemotion Amsterdam 2019

Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
Catalin Dumitru
 
This is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdfThis is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdf
indiaartz
 

Similar to Matteo Antony Mistretta - React, the Inglorious way - Codemotion Amsterdam 2019 (20)

React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
JBUG 11 - Scala For Java Programmers
JBUG 11 - Scala For Java ProgrammersJBUG 11 - Scala For Java Programmers
JBUG 11 - Scala For Java Programmers
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
 
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
 
How Reactive do we need to be
How Reactive do we need to beHow Reactive do we need to be
How Reactive do we need to be
 
Indeed My Jobs: A case study in ReactJS and Redux (Meetup talk March 2016)
Indeed My Jobs: A case study in ReactJS and Redux (Meetup talk March 2016)Indeed My Jobs: A case study in ReactJS and Redux (Meetup talk March 2016)
Indeed My Jobs: A case study in ReactJS and Redux (Meetup talk March 2016)
 
Functional programming techniques in real-world microservices
Functional programming techniques in real-world microservicesFunctional programming techniques in real-world microservices
Functional programming techniques in real-world microservices
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
 
Road to react hooks
Road to react hooksRoad to react hooks
Road to react hooks
 
ReactJS
ReactJSReactJS
ReactJS
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRx
 
Data in Motion: Streaming Static Data Efficiently 2
Data in Motion: Streaming Static Data Efficiently 2Data in Motion: Streaming Static Data Efficiently 2
Data in Motion: Streaming Static Data Efficiently 2
 
Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303
 
Data in Motion: Streaming Static Data Efficiently
Data in Motion: Streaming Static Data EfficientlyData in Motion: Streaming Static Data Efficiently
Data in Motion: Streaming Static Data Efficiently
 
React Back to the Future
React Back to the FutureReact Back to the Future
React Back to the Future
 
This is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdfThis is a C# project . I am expected to create as this image shows. .pdf
This is a C# project . I am expected to create as this image shows. .pdf
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wild
 
Building complex User Interfaces with Sitecore and React
Building complex User Interfaces with Sitecore and ReactBuilding complex User Interfaces with Sitecore and React
Building complex User Interfaces with Sitecore and React
 
Swift 함수 커링 사용하기
Swift 함수 커링 사용하기Swift 함수 커링 사용하기
Swift 함수 커링 사용하기
 

More from Codemotion

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Recently uploaded (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

Matteo Antony Mistretta - React, the Inglorious way - Codemotion Amsterdam 2019

  • 1. React, The Inglorious Way Matteo Antony Mistretta Inglorious Coderz @antonymistretta
  • 2. Why React is evolving rapidly A few rules, lots of strategies Learning them makes us better coders
  • 5. 42 -1 +1 class Counter extends Component { constructor(props) { super(props) this.state = { count: props.initialCount } this.increment = this.increment.bind(this) } increment() { this.setState({ count: this.state.count + 1 }) } decrement() { this.setState({ count: this.state.count - 1 }) } render() { const { count } = this.state return ( <div> <h1>{count}</h1> <div className="input-group"> <button onClick={this.decrement.bind(this)}>-1</button> <input type="number" value={count} onChange={event => { this.setState({ count: parseInt(event.target.value) }) }} /> <button onClick={this.increment}>+1</button> </div> </div> ) } } render(<Counter initialCount={42} />) 42
  • 6. 42 -1 +1 class Counter extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { const { count } = this.state return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={this.decrement}>-1</button> <input type="number" value={count} onChange={this.handleChange} /> <button onClick={this.increment}>+1</button> </div> </> ) } } render(<Counter initialCount={42} />) 42
  • 8. 42 -1 +1 class Counter extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { const { count } = this.state return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={this.decrement}>-1</button> <input type="number" value={count} onChange={this.handleChange} /> <button onClick={this.increment}>+1</button> </div> </> ) } } render(<Counter initialCount={42} />) 42
  • 9. 42 -1 +1 class CounterContainer extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { return ( <Counter count={this.state.count} increment={this.increment} decrement={this.decrement} handleChange={this.handleChange} /> ) } } function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<CounterContainer initialCount={42} />) 42
  • 10. 42 -1 +1 class CounterContainer extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { // NOTE: this is bad return Counter({ count: this.state.count, increment: this.increment, decrement: this.decrement, handleChange: this.handleChange, }) } } function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<CounterContainer initialCount={42} />) 42
  • 12. 42 -1 +1 class CounterContainer extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { return ( <Counter count={this.state.count} increment={this.increment} decrement={this.decrement} handleChange={this.handleChange} /> ) } } function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<CounterContainer initialCount={42} />) 42
  • 13. 42 -1 +1 const withCounter = Enhanced => class CounterContainer extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { return ( <Enhanced count={this.state.count} increment={this.increment} decrement={this.decrement} handleChange={this.handleChange} /> ) } } Counter = withCounter(Counter) function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<Counter initialCount={42} />) 42
  • 14. 42 -1 +1 const enhance = compose( withState('count', 'setCount', ({ initialCount }) => initialCount), withHandlers({ increment: ({ setCount }) => () => setCount(count => count + 1), decrement: ({ setCount }) => () => setCount(count => count - 1), handleChange: ({ setCount }) => event => setCount(parseInt(event.target.value)), }), pure, ) Counter = enhance(Counter) function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<Counter initialCount={42} />) 42
  • 16. Hello world! function Parent() { return ( <Wrapper> <Child who="world" /> </Wrapper> ) } function Child({ who }) { return `Hello ${who}!` } function Wrapper({ children }) { return <h1>{children}</h1> } render(Parent)
  • 17. Hello WORLD! function Parent() { return <Wrapper who="world" Component={Child} /> } function Child({ who }) { return `Hello ${who}!` } function Wrapper({ who, Component }) { const shoutedWho = who.toUpperCase() return ( <h1> <Component who={shoutedWho} /> </h1> ) } render(Parent)
  • 18. Hello WORLDz! function Parent() { return <Wrapper who="world" render={who => <Child who={who + 'z'} />} /> } function Child({ who }) { return `Hello ${who}!` } function Wrapper({ who, render }) { const shoutedWho = who.toUpperCase() return <h1>{render(shoutedWho)}</h1> } render(Parent)
  • 19. Hello WORLDz! function Parent() { return <Wrapper who="world">{who => <Child who={who + 'z'} />}</Wrapper> } function Child({ who }) { return `Hello ${who}!` } function Wrapper({ children, who }) { const shoutedWho = who.toUpperCase() return <h1>{children(shoutedWho)}</h1> } render(Parent)
  • 20. 42 -1 +1 class CounterContainer extends PureComponent { state = { count: this.props.initialCount } increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) render() { return ( <Counter count={this.state.count} increment={this.increment} decrement={this.decrement} handleChange={this.handleChange} /> ) } } function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<CounterContainer initialCount={42} />) 42
  • 21. 42 -1 +1 class CounterContainer extends PureComponent { increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) state = { count: this.props.initialCount, increment: this.increment, decrement: this.decrement, handleChange: this.handleChange, } render() { return this.props.children(this.state) } } function Counter({ initialCount }) { return ( <CounterContainer initialCount={initialCount}> {({ count, increment, decrement, handleChange }) => ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> )} </CounterContainer> ) } render(<Counter initialCount={42} />) 42
  • 22. 42 -1 +1 class CounterContainer extends PureComponent { increment = () => this.setState(({ count }) => ({ count: count + 1 })) decrement = () => this.setState(({ count }) => ({ count: count - 1 })) setCount = count => this.setState({ count }) handleChange = event => this.setCount(parseInt(event.target.value)) state = { count: this.props.initialCount, increment: this.increment, decrement: this.decrement, handleChange: this.handleChange, } render() { return this.props.children(this.state) } } class Counter extends PureComponent { renderCounter = ({ count, increment, decrement, handleChange }) => ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) render() { return ( <CounterContainer initialCount={this.props.initialCount}> {this.renderCounter} </CounterContainer> ) } } render(<Counter initialCount={42} />) 42
  • 24. They separate stateful logic They are composable functions They allow us to go fully functional They keep our component hierarchy flat
  • 25. 42 -1 +1 const enhance = compose( withState('count', 'setCount', ({ initialCount }) => initialCount), withHandlers({ increment: ({ setCount }) => () => setCount(count => count + 1), decrement: ({ setCount }) => () => setCount(count => count - 1), handleChange: ({ setCount }) => event => setCount(parseInt(event.target.value)), }), pure, ) Counter = enhance(Counter) function Counter({ count, increment, decrement, handleChange }) { return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<Counter initialCount={42} />) 42
  • 26. 42 -1 +1 function useCounter(initialCount) { const [count, setCount] = useState(initialCount) const increment = () => setCount(count + 1) const decrement = () => setCount(count - 1) const handleChange = event => setCount(parseInt(event.target.value)) return { count, increment, decrement, handleChange } } Counter = memo(Counter) function Counter({ initialCount }) { const { count, increment, decrement, handleChange } = useCounter(initialCount) return ( <> <h1>{count}</h1> <div className="input-group"> <button onClick={decrement}>-1</button> <input type="number" value={count} onChange={handleChange} /> <button onClick={increment}>+1</button> </div> </> ) } render(<Counter initialCount={42} />) 42
  • 28.
  • 29.
  • 30.
  • 31. Hello WORLD! function Hello({ who }) { return <h1>{`Hello ${who}!`}</h1> } const enhance = Enhanced => ({ who, ...props }) => { if (!who.length) return 'Name too short' const shoutedWho = who.toUpperCase() return <Enhanced {...props} who={shoutedWho} /> } Hello = enhance(Hello) render(<Hello who="world" />)
  • 32. world though ly tual issey const SimpleList = ({ whos }) => ( <ul style={styles.list}> {whos.map(who => ( <li>{who}</li> ))} </ul> ) const ComplexList = ({ renderEven, renderOdd, whos }) => ( <ul style={styles.list}> {whos.map((who, index) => (index % 2 ? renderEven(who) : renderOdd(who)))} </ul> ) const Parent = ({ whos, simple }) => { if (simple) return <SimpleList whos={whos} /> return ( <ComplexList renderEven={who => <li style={styles.even}>{'Even ' + who}</li>} renderOdd={who => <li style={styles.odd}>{'Odd ' + who}</li>} whos={whos} /> ) } render( <Parent whos={['world', 'though', 'ly', 'tual', 'issey']} simple={true} />, ) const styles = { list: { textAlign: 'left' }, odd: { color: 'grey' }, even: { color: 'cornflowerblue' }, }
  • 33. Which to use? Classes: getSnapshotBeforeUpdate / componentDidCatch HOCs: proxy / before render (change props, prevent renders) Render Props: mix logic / multiple sub-items / switch behavior Hooks: everything else