SlideShare une entreprise Scribd logo
1  sur  85
Télécharger pour lire hors ligne
AND INTRO TO HOOKS
Nir Hadassi
Software Engineer @ Soluto
REACT NEW FEATURES
This talk was supposed to be about...
High-Order-Components
and Recompose
But then...
And then...
@TheRealMohaz
About Myself
Nir Hadassi
4years
working at
Soluto
3years
working with
React
nirsky
What are React Hooks?
“Hooks lets you use state and
other React features without
writing a class.”
Introduced on React v16.7.0-alpha
Why?
CLASSES ARE
BAD
Why classes are bad?
● Complex components become hard to understand
● Classes confuse people (notorious this..)
● Classes confuse machines (don’t minify well)
● It’s hard to reuse stateful logic between classes
Agenda
1. Hooks Intro
a. useState
b. useRef
c. useContext
d. useEffect
2. Memo
3. Lazy
useState
Class with state
class CounterButton extends Component {
constructor() {
super();
this.state = {
count: 0
}
}
render() {
return <button onClick={() => this.setState(prevState => ({ count: prevState.count + 1
}))}>
{ this.state.count }
</button>
}
}
With useState
import React, { useState } from 'react';
const Counter = props => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>
{ count }
</button>
}
With useState
import React, { useState } from 'react';
const Counter = props => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>
{ count }
</button>
}
With useState
import React, { useState } from 'react';
const Counter = props => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>
{ count }
</button>
}
With useState
import React, { useState } from 'react';
const Counter = props => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>
{ count }
</button>
}
Multiple State Variables
const Player = props => {
const [volume, setVolume] = useState(0);
const [position, setPosition] = useState(0);
const [paused, setPaused] = useState(true);
const onClick = () => {
setPosition(0);
setPaused(false);
}
}
Multiple State Variables
const Player = props => {
const [state, setState] = useState({
volume: 0,
position: 0,
paused: true
});
const onClick = () => {
setState({
...state,
position: 0,
paused: false
})
}
}
useContext
Using context without hooks
import { ThemeContext } from './context';
const Counter = props => {
const [count, setCount] = useState(0);
return (
<ThemeContext.Consumer>
{theme => (
<Button theme={theme} onClick={...}>
{count}
</Button>
)}
</ThemeContext.Consumer>
)
}
useContext hook
import React, { useContext } from 'react';
import { ThemeContext } from './context';
const Counter = props => {
const [count, setCount] = useState(0);
const theme = useContext(ThemeContext)
return (
<Button theme={theme} onClick={...}>
{count}
</Button>
)
}
useContext hook
import React, { useContext } from 'react';
import { ThemeContext } from './context';
const Counter = props => {
const [count, setCount] = useState(0);
const theme = useContext(ThemeContext)
return (
<Button theme={theme} onClick={...}>
{count}
</Button>
)
}
useRef
useRef
const TextInputWithFocusButton = (props) => {
const inputRef = useRef();
return (
<>
<input ref={inputRef} type="text" />
<button onClick={() => inputRef.current.focus()}>
Focus the input
</button>
</>
);
}
useRef
const TextInputWithFocusButton = (props) => {
const inputRef = useRef();
return (
<>
<input ref={inputRef} type="text" />
<button onClick={() => inputRef.current.focus()}>
Focus the input
</button>
</>
);
}
useRef
const TextInputWithFocusButton = (props) => {
const inputRef = useRef();
return (
<>
<input ref={inputRef} type="text" />
<button onClick={() => inputRef.current.focus()}>
Focus the input
</button>
</>
);
}
useRef
const TextInputWithFocusButton = (props) => {
const inputRef = useRef();
return (
<>
<input ref={inputRef} type="text" />
<button onClick={() => inputRef.current.focus()}>
Focus the input
</button>
</>
);
}
Rules of Hooks
● Only Call Hooks at the Top Level!
○ Don’t call Hooks inside loops, conditions, or nested functions
○ Order Matters!
● Only Call Hooks from React Functions
○ Or from custom hooks
Under the hood
MyComponent
Memoized State Array
Hooks
Dispatcher
MyComponent
- Initial Render
useState()
useRef()
useState()
State hook
Ref hook
State hook
Slot 0
Slot 1
Slot 2
Under the hood
MyComponent
Memoized State Array
Hooks
Dispatcher
useState()
useRef()
useState()
State hook
Ref hook
State hook
useState()
Search on Slot 0
MyComponent
- Initial Render
MyComponent
- 2nd Render
Under the hood
MyComponent
Memoized State Array
Hooks
Dispatcher
useState()
useRef()
useState()
State hook
Ref hook
State hook
useState()
useRef()
useState()
Search on Slot 1MyComponent
- 2nd Render
MyComponent
- Initial Render
useEffect
Executing something on every render using lifecycle
class CounterButton extends Component {
constructor() {
super();
this.state = {count: 0}
}
componentDidMount() {
console.log(`The count is now ${this.state.count}`)
}
componentDidUpdate() {
console.log(`The count is now ${this.state.count}`)
}
render() {
return <button onClick={() => this.setState(prevState => ({ count: prevState.count + 1 }))}>
{ this.state.count }
</button>
}
}
Executing something on every render using useEffect
const Counter = props => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`The count is now ${count}`)
});
return <button onClick={() => setCount(count + 1)}>
{ count }
</button>
}
Executing something on every render using useEffect
const Counter = props => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`The count is now ${count}`)
});
return <button onClick ={() => setCount(count + 1)}>
{ count }
</button>
}
Effects with Cleanup
useEffect(() => {
console.log(`The count is now ${count}`);
return function cleanup() {
console.log('cleaning up');
}
});
Effects with Cleanup
useEffect(() => {
console.log(`The count is now ${count}`);
return function cleanup() {
console.log('cleaning up');
}
});
Should my effect run on
every render?
Consider the next scenario...
//timer changes every 100ms
const Counter = ({timer}) => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`The count is now ${count}`)
});
return <MyComponent onClick={() => setCount(count + 1)} timer={timer}>
{ count }
</MyComponent>
}
useEffect 2nd parameter
useEffect(() => {
console.log(`The count is now ${count}`)
}, [count]);
componentWillReceiveProps
componentWillReceiveProps(nextProps) {
if (this.props.timer !== nextProps.timer) {
console.log(`The timer is now ${nextProps.timer}`)
}
}
componentWillReceiveProps - hooks version
useEffect(() => {
console.log(`Timer is now ${props.timer}`);
}, [props.timer]);
componentDidMount - hooks version
useEffect(() => {
console.log(`I just mounted!`)
}, []);
componentWillUnmount - hooks version
useEffect(() => {
return function cleanup(){
console.log(`I'm unmounting!`)
}
}, []);
Let’s combine what
we learned so far
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage =
this.onNewMessage.bind(this);
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
onNewMessage(message) {
this.setState({
messages: [...this.state.messages, message]
})
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
componentDidMount () {
SocketClient.subscribeForNewMessages (
this.props.roomId,
this.onNewMessage
);
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
componentWillUnmount () {
SocketClient.unsubscribe(
this.props.roomId
);
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.roomId !== this.props.roomId) {
this.setState({ messages: [] });
SocketClient.unsubscribe(this.props.roomId);
SocketClient.subscribeForNewMessages(
nextProps.roomId,
this.onNewMessage
);
}
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
render() {
return this.state.messages
.map((text, i) =>
<div key={i}>{text}</div>
)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([...messages, message]);
SocketClient.subscribeForNewMessages (roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([ ...messages, message]);
SocketClient.subscribeForNewMessages(roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([ ...messages, message]);
SocketClient.subscribeForNewMessages(roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([ ...messages, message]);
SocketClient.subscribeForNewMessages(roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([...messages, message]);
SocketClient.subscribeForNewMessages(roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([ ...messages, message]);
SocketClient.subscribeForNewMessages (roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
const ChatPage = ({ roomId }) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([ ...messages, message]);
SocketClient.subscribeForNewMessages(roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages.map((text, i) => <div key={i}>{text}</div>)
}
Custom Hooks
What are Custom Hooks?
● Basically functions that run hooks
● Like any other function - they can can take any args and return
whatever you want
● By convention - custom hook name start with “use”
● Like any other hook - must be called on the top level of our
components
This is the custom hook:
const useChatMessages = (roomId) => {
const [messages, setMessages] = useState([]);
useEffect(() => {
setMessages([]);
const onNewMessage = (message) => setMessages([...messages, message]);
SocketClient.subscribeForNewMessages(roomId, onNewMessage);
return () => SocketClient.unsubscribe(roomId);
}, [roomId]);
return messages;
}
This is the (very short) component:
const ChatPage = ({ roomId }) => {
const messages = useChatMessages(roomId);
return messages.map((text, i) =>
<div key={i}>{text}</div>)
}
class ChatPage extends Component {
constructor() {
super();
this.state = {
messages: []
}
this.onNewMessage = this.onNewMessage. bind(this);
}
componentDidMount () {
SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage );
}
componentWillUnmount () {
SocketClient. unsubscribe (this.props.roomId);
}
componentWillReceiveProps (nextProps ) {
if (nextProps .roomId !== this.props.roomId) {
this.setState ({ messages: [] });
SocketClient. unsubscribe (this.props.roomId);
SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage );
}
}
onNewMessage (message) {
this.setState ({ messages: [...this.state.messages , message] })
}
render() {
return this.state.messages. map((text, i) => <div key={i}>{text}</div>)
}
}
Remember how it used to look?28 lines vs. 5 with custom hook
Custom Hooks allow us to..
● Easily share code
● Keep our components clean and readable
● Use Hooks from npm packages
Other hooks
● useReducer
● useCallback
● useMemo
● useImperativeMethods
● useLayoutEffect
Memo
React.memo
PureComponent for function components
import React, {memo} from 'react';
const MyComponent = props => { ... }
export default memo(MyComponent);
Introduced on React 16.6
React.memo
PureComponent for function components
import React, {memo} from 'react';
const MyComponent = props => { ... }
const areEqual = (prevProps, nextProps) => { ... }
export default memo(MyComponent, areEqual);
Introduced on React 16.6
<MyComponent x={1} y={2}/>
DOM
render
x=1
y=2
Memo
Cache
<MyComponent x={2} y={2}/>
render
x=2
y=2
<MyComponent x={2} y={3}/>
1
2
3
Rendering “MyComponent” with Memo
x=1
y=2
x=2
y=2
areEqual = (prev, next) => prev.x === next.x
Suspense + Lazy
Lazy
Code-Splitting
import React, { lazy } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent' ));
const MyComponent = (props) =>
<div>
<OtherComponent/>
</div>
Introduced on React 16.6
Lazy
Code-Splitting
import React, { lazy } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const MyComponent = (props) =>
<div>
<OtherComponent/>
</div>
Introduced on React 16.6
Lazy
Code-Splitting
import React, { lazy } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent' ));
const MyComponent = (props) =>
<div>
<OtherComponent/>
</div>
Introduced on React 16.6
Lazy
Code-Splitting
import React, { lazy } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const MyComponent = (props) =>
<div>
<OtherComponent/>
</div>
Introduced on React 16.6
Lazy + Suspense
Code-Splitting
import React, { lazy, Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent' ));
const MyComponent = (props) =>
<div>
<Suspense fallback={<div>Loading..</div>}>
<OtherComponent />
</Suspense>
</div>
Introduced on React 16.6
Lazy + Suspense
Code-Splitting
import React, { lazy, Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const MyComponent = (props) =>
<div>
<Suspense fallback ={<div>Loading..</div>}>
<OtherComponent />
</Suspense>
</div>
Introduced on React 16.6
Lazy + Suspense
Code-Splitting
import React, { lazy, Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const MyComponent = (props) =>
<div>
<Suspense fallback={<div>Loading..</div>}>
<OtherComponent />
</Suspense>
</div>
Introduced on React 16.6
const Home = lazy(() => import('./components/Home ));
const Posts = lazy(() => import('./components/Posts' ));
const App = () => (
<Router>
<Suspense fallback={<Loading />}>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/posts" component={Posts} />
</Switch>
</Suspense>
</Router>
)
Hook me up with
Questions
nirsky
Nir_Hadassi
THANKS!
nirsky
Nir_Hadassi

Contenu connexe

Tendances

[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
洪 鹏发
 

Tendances (20)

Intro to React
Intro to ReactIntro to React
Intro to React
 
React workshop
React workshopReact workshop
React workshop
 
React Hooks
React HooksReact Hooks
React Hooks
 
React-JS Component Life-cycle Methods
React-JS Component Life-cycle MethodsReact-JS Component Life-cycle Methods
React-JS Component Life-cycle Methods
 
React state
React  stateReact  state
React state
 
React JS - Introduction
React JS - IntroductionReact JS - Introduction
React JS - Introduction
 
An introduction to React.js
An introduction to React.jsAn introduction to React.js
An introduction to React.js
 
Understanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree TechnologiesUnderstanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree Technologies
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
 
Introduction to ReactJS
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJS
 
What is component in reactjs
What is component in reactjsWhat is component in reactjs
What is component in reactjs
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
 
Reactjs
Reactjs Reactjs
Reactjs
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
reactJS
reactJSreactJS
reactJS
 
Basics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdfBasics of React Hooks.pptx.pdf
Basics of React Hooks.pptx.pdf
 
React Context API
React Context APIReact Context API
React Context API
 
Introduction to ReactJS
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJS
 
Introduction to React JS
Introduction to React JSIntroduction to React JS
Introduction to React JS
 

Similaire à React new features and intro to Hooks

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
 

Similaire à React new features and intro to Hooks (20)

Road to react hooks
Road to react hooksRoad to react hooks
Road to react hooks
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
 
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!
 
N Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React NativeN Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React Native
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
How do we use hooks
How do we use hooksHow do we use hooks
How do we use hooks
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
 
Matteo Antony Mistretta - Refactoring into React hooks - Codemotion Rome 2019
Matteo Antony Mistretta - Refactoring into React hooks - Codemotion Rome 2019Matteo Antony Mistretta - Refactoring into React hooks - Codemotion Rome 2019
Matteo Antony Mistretta - Refactoring into React hooks - Codemotion Rome 2019
 
React JS Hooks Sheet .pdf
React JS Hooks Sheet .pdfReact JS Hooks Sheet .pdf
React JS Hooks Sheet .pdf
 
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
 
Higher Order Components and Render Props
Higher Order Components and Render PropsHigher Order Components and Render Props
Higher Order Components and Render Props
 
react-hooks.pdf
react-hooks.pdfreact-hooks.pdf
react-hooks.pdf
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
 
React Back to the Future
React Back to the FutureReact Back to the Future
React Back to the Future
 
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)
 
React ES5 to ES6 | React ES5 vs ES6 | React Tutorial for Beginners | React on...
React ES5 to ES6 | React ES5 vs ES6 | React Tutorial for Beginners | React on...React ES5 to ES6 | React ES5 vs ES6 | React Tutorial for Beginners | React on...
React ES5 to ES6 | React ES5 vs ES6 | React Tutorial for Beginners | React on...
 
JavaScript Refactoring
JavaScript RefactoringJavaScript Refactoring
JavaScript Refactoring
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practices
 
Creating a Facebook Clone - Part XXIX - Transcript.pdf
Creating a Facebook Clone - Part XXIX - Transcript.pdfCreating a Facebook Clone - Part XXIX - Transcript.pdf
Creating a Facebook Clone - Part XXIX - Transcript.pdf
 
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
 

Plus de Soluto

Can Kubernetes Keep a Secret? - Women in AppSec Webinar
Can Kubernetes Keep a Secret? - Women in AppSec WebinarCan Kubernetes Keep a Secret? - Women in AppSec Webinar
Can Kubernetes Keep a Secret? - Women in AppSec Webinar
Soluto
 
FTRD - Can Kubernetes Keep a Secret?
FTRD -  Can Kubernetes Keep a Secret?FTRD -  Can Kubernetes Keep a Secret?
FTRD - Can Kubernetes Keep a Secret?
Soluto
 
Can Kubernetes Keep a Secret?
Can Kubernetes Keep a Secret?Can Kubernetes Keep a Secret?
Can Kubernetes Keep a Secret?
Soluto
 

Plus de Soluto (20)

Solving trust issues at scale - AppSec California
Solving trust issues at scale - AppSec CaliforniaSolving trust issues at scale - AppSec California
Solving trust issues at scale - AppSec California
 
Solving trust issues at scale
Solving trust issues at scaleSolving trust issues at scale
Solving trust issues at scale
 
Things I wish someone had told me about Istio, Omer Levi Hevroni
Things I wish someone had told me about Istio, Omer Levi HevroniThings I wish someone had told me about Istio, Omer Levi Hevroni
Things I wish someone had told me about Istio, Omer Levi Hevroni
 
Can Kubernetes Keep a Secret? - Women in AppSec Webinar
Can Kubernetes Keep a Secret? - Women in AppSec WebinarCan Kubernetes Keep a Secret? - Women in AppSec Webinar
Can Kubernetes Keep a Secret? - Women in AppSec Webinar
 
FTRD - Can Kubernetes Keep a Secret?
FTRD -  Can Kubernetes Keep a Secret?FTRD -  Can Kubernetes Keep a Secret?
FTRD - Can Kubernetes Keep a Secret?
 
The Dark Side of Monitoring
The Dark Side of MonitoringThe Dark Side of Monitoring
The Dark Side of Monitoring
 
Hacking like a FED
Hacking like a FEDHacking like a FED
Hacking like a FED
 
Monitoria@Icinga camp berlin
Monitoria@Icinga camp berlinMonitoria@Icinga camp berlin
Monitoria@Icinga camp berlin
 
Can Kubernetes Keep a Secret?
Can Kubernetes Keep a Secret?Can Kubernetes Keep a Secret?
Can Kubernetes Keep a Secret?
 
Kamus intro
Kamus introKamus intro
Kamus intro
 
Secure Your Pipeline
Secure Your PipelineSecure Your Pipeline
Secure Your Pipeline
 
Secure the Pipeline - OWASP Poland Day 2018
Secure the Pipeline - OWASP Poland Day 2018Secure the Pipeline - OWASP Poland Day 2018
Secure the Pipeline - OWASP Poland Day 2018
 
Monitoria@reversim
Monitoria@reversimMonitoria@reversim
Monitoria@reversim
 
Languages don't matter anymore!
Languages don't matter anymore!Languages don't matter anymore!
Languages don't matter anymore!
 
Security Testing for Containerized Applications
Security Testing for Containerized ApplicationsSecurity Testing for Containerized Applications
Security Testing for Containerized Applications
 
Owasp glue
Owasp glueOwasp glue
Owasp glue
 
Unify logz with fluentd
Unify logz with fluentdUnify logz with fluentd
Unify logz with fluentd
 
Storing data in Redis like a pro
Storing data in Redis like a proStoring data in Redis like a pro
Storing data in Redis like a pro
 
Monitor all the thingz slideshare
Monitor all the thingz slideshareMonitor all the thingz slideshare
Monitor all the thingz slideshare
 
Authentication without Authentication - AppSec California
Authentication without Authentication - AppSec CaliforniaAuthentication without Authentication - AppSec California
Authentication without Authentication - AppSec California
 

Dernier

Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night StandCall Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
amitlee9823
 
notes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.pptnotes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.ppt
MsecMca
 
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Christo Ananth
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 

Dernier (20)

Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
 
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
VIP Model Call Girls Kothrud ( Pune ) Call ON 8005736733 Starting From 5K to ...
 
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night StandCall Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 
Bhosari ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For ...
Bhosari ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For ...Bhosari ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For ...
Bhosari ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For ...
 
Call Girls Walvekar Nagar Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Walvekar Nagar Call Me 7737669865 Budget Friendly No Advance BookingCall Girls Walvekar Nagar Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Walvekar Nagar Call Me 7737669865 Budget Friendly No Advance Booking
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
 
Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . ppt
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
notes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.pptnotes on Evolution Of Analytic Scalability.ppt
notes on Evolution Of Analytic Scalability.ppt
 
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdfONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
ONLINE FOOD ORDER SYSTEM PROJECT REPORT.pdf
 
chapter 5.pptx: drainage and irrigation engineering
chapter 5.pptx: drainage and irrigation engineeringchapter 5.pptx: drainage and irrigation engineering
chapter 5.pptx: drainage and irrigation engineering
 
Call Girls Wakad Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Wakad Call Me 7737669865 Budget Friendly No Advance BookingCall Girls Wakad Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Wakad Call Me 7737669865 Budget Friendly No Advance Booking
 
Double rodded leveling 1 pdf activity 01
Double rodded leveling 1 pdf activity 01Double rodded leveling 1 pdf activity 01
Double rodded leveling 1 pdf activity 01
 
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
 
UNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its PerformanceUNIT - IV - Air Compressors and its Performance
UNIT - IV - Air Compressors and its Performance
 
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
 
Online banking management system project.pdf
Online banking management system project.pdfOnline banking management system project.pdf
Online banking management system project.pdf
 

React new features and intro to Hooks

  • 1. AND INTRO TO HOOKS Nir Hadassi Software Engineer @ Soluto REACT NEW FEATURES
  • 2. This talk was supposed to be about... High-Order-Components and Recompose
  • 5. @TheRealMohaz About Myself Nir Hadassi 4years working at Soluto 3years working with React nirsky
  • 6. What are React Hooks? “Hooks lets you use state and other React features without writing a class.” Introduced on React v16.7.0-alpha
  • 8. Why classes are bad? ● Complex components become hard to understand ● Classes confuse people (notorious this..) ● Classes confuse machines (don’t minify well) ● It’s hard to reuse stateful logic between classes
  • 9. Agenda 1. Hooks Intro a. useState b. useRef c. useContext d. useEffect 2. Memo 3. Lazy
  • 11.
  • 12. Class with state class CounterButton extends Component { constructor() { super(); this.state = { count: 0 } } render() { return <button onClick={() => this.setState(prevState => ({ count: prevState.count + 1 }))}> { this.state.count } </button> } }
  • 13. With useState import React, { useState } from 'react'; const Counter = props => { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}> { count } </button> }
  • 14. With useState import React, { useState } from 'react'; const Counter = props => { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}> { count } </button> }
  • 15. With useState import React, { useState } from 'react'; const Counter = props => { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}> { count } </button> }
  • 16. With useState import React, { useState } from 'react'; const Counter = props => { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}> { count } </button> }
  • 17. Multiple State Variables const Player = props => { const [volume, setVolume] = useState(0); const [position, setPosition] = useState(0); const [paused, setPaused] = useState(true); const onClick = () => { setPosition(0); setPaused(false); } }
  • 18. Multiple State Variables const Player = props => { const [state, setState] = useState({ volume: 0, position: 0, paused: true }); const onClick = () => { setState({ ...state, position: 0, paused: false }) } }
  • 20. Using context without hooks import { ThemeContext } from './context'; const Counter = props => { const [count, setCount] = useState(0); return ( <ThemeContext.Consumer> {theme => ( <Button theme={theme} onClick={...}> {count} </Button> )} </ThemeContext.Consumer> ) }
  • 21. useContext hook import React, { useContext } from 'react'; import { ThemeContext } from './context'; const Counter = props => { const [count, setCount] = useState(0); const theme = useContext(ThemeContext) return ( <Button theme={theme} onClick={...}> {count} </Button> ) }
  • 22. useContext hook import React, { useContext } from 'react'; import { ThemeContext } from './context'; const Counter = props => { const [count, setCount] = useState(0); const theme = useContext(ThemeContext) return ( <Button theme={theme} onClick={...}> {count} </Button> ) }
  • 24. useRef const TextInputWithFocusButton = (props) => { const inputRef = useRef(); return ( <> <input ref={inputRef} type="text" /> <button onClick={() => inputRef.current.focus()}> Focus the input </button> </> ); }
  • 25. useRef const TextInputWithFocusButton = (props) => { const inputRef = useRef(); return ( <> <input ref={inputRef} type="text" /> <button onClick={() => inputRef.current.focus()}> Focus the input </button> </> ); }
  • 26. useRef const TextInputWithFocusButton = (props) => { const inputRef = useRef(); return ( <> <input ref={inputRef} type="text" /> <button onClick={() => inputRef.current.focus()}> Focus the input </button> </> ); }
  • 27. useRef const TextInputWithFocusButton = (props) => { const inputRef = useRef(); return ( <> <input ref={inputRef} type="text" /> <button onClick={() => inputRef.current.focus()}> Focus the input </button> </> ); }
  • 28. Rules of Hooks ● Only Call Hooks at the Top Level! ○ Don’t call Hooks inside loops, conditions, or nested functions ○ Order Matters! ● Only Call Hooks from React Functions ○ Or from custom hooks
  • 29. Under the hood MyComponent Memoized State Array Hooks Dispatcher MyComponent - Initial Render useState() useRef() useState() State hook Ref hook State hook Slot 0 Slot 1 Slot 2
  • 30. Under the hood MyComponent Memoized State Array Hooks Dispatcher useState() useRef() useState() State hook Ref hook State hook useState() Search on Slot 0 MyComponent - Initial Render MyComponent - 2nd Render
  • 31. Under the hood MyComponent Memoized State Array Hooks Dispatcher useState() useRef() useState() State hook Ref hook State hook useState() useRef() useState() Search on Slot 1MyComponent - 2nd Render MyComponent - Initial Render
  • 33. Executing something on every render using lifecycle class CounterButton extends Component { constructor() { super(); this.state = {count: 0} } componentDidMount() { console.log(`The count is now ${this.state.count}`) } componentDidUpdate() { console.log(`The count is now ${this.state.count}`) } render() { return <button onClick={() => this.setState(prevState => ({ count: prevState.count + 1 }))}> { this.state.count } </button> } }
  • 34. Executing something on every render using useEffect const Counter = props => { const [count, setCount] = useState(0); useEffect(() => { console.log(`The count is now ${count}`) }); return <button onClick={() => setCount(count + 1)}> { count } </button> }
  • 35. Executing something on every render using useEffect const Counter = props => { const [count, setCount] = useState(0); useEffect(() => { console.log(`The count is now ${count}`) }); return <button onClick ={() => setCount(count + 1)}> { count } </button> }
  • 36. Effects with Cleanup useEffect(() => { console.log(`The count is now ${count}`); return function cleanup() { console.log('cleaning up'); } });
  • 37. Effects with Cleanup useEffect(() => { console.log(`The count is now ${count}`); return function cleanup() { console.log('cleaning up'); } });
  • 38. Should my effect run on every render? Consider the next scenario...
  • 39. //timer changes every 100ms const Counter = ({timer}) => { const [count, setCount] = useState(0); useEffect(() => { console.log(`The count is now ${count}`) }); return <MyComponent onClick={() => setCount(count + 1)} timer={timer}> { count } </MyComponent> }
  • 40.
  • 41. useEffect 2nd parameter useEffect(() => { console.log(`The count is now ${count}`) }, [count]);
  • 42. componentWillReceiveProps componentWillReceiveProps(nextProps) { if (this.props.timer !== nextProps.timer) { console.log(`The timer is now ${nextProps.timer}`) } }
  • 43. componentWillReceiveProps - hooks version useEffect(() => { console.log(`Timer is now ${props.timer}`); }, [props.timer]);
  • 44. componentDidMount - hooks version useEffect(() => { console.log(`I just mounted!`) }, []);
  • 45. componentWillUnmount - hooks version useEffect(() => { return function cleanup(){ console.log(`I'm unmounting!`) } }, []);
  • 46. Let’s combine what we learned so far
  • 47.
  • 48. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } }
  • 49. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage.bind(this); }
  • 50. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } onNewMessage(message) { this.setState({ messages: [...this.state.messages, message] }) }
  • 51. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } componentDidMount () { SocketClient.subscribeForNewMessages ( this.props.roomId, this.onNewMessage ); }
  • 52. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } componentWillUnmount () { SocketClient.unsubscribe( this.props.roomId ); }
  • 53. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } componentWillReceiveProps(nextProps) { if (nextProps.roomId !== this.props.roomId) { this.setState({ messages: [] }); SocketClient.unsubscribe(this.props.roomId); SocketClient.subscribeForNewMessages( nextProps.roomId, this.onNewMessage ); } }
  • 54. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } render() { return this.state.messages .map((text, i) => <div key={i}>{text}</div> ) }
  • 55. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([...messages, message]); SocketClient.subscribeForNewMessages (roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 56. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([ ...messages, message]); SocketClient.subscribeForNewMessages(roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 57. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([ ...messages, message]); SocketClient.subscribeForNewMessages(roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 58. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([ ...messages, message]); SocketClient.subscribeForNewMessages(roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 59. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([...messages, message]); SocketClient.subscribeForNewMessages(roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 60. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([ ...messages, message]); SocketClient.subscribeForNewMessages (roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 61. const ChatPage = ({ roomId }) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([ ...messages, message]); SocketClient.subscribeForNewMessages(roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 63. What are Custom Hooks? ● Basically functions that run hooks ● Like any other function - they can can take any args and return whatever you want ● By convention - custom hook name start with “use” ● Like any other hook - must be called on the top level of our components
  • 64. This is the custom hook: const useChatMessages = (roomId) => { const [messages, setMessages] = useState([]); useEffect(() => { setMessages([]); const onNewMessage = (message) => setMessages([...messages, message]); SocketClient.subscribeForNewMessages(roomId, onNewMessage); return () => SocketClient.unsubscribe(roomId); }, [roomId]); return messages; }
  • 65. This is the (very short) component: const ChatPage = ({ roomId }) => { const messages = useChatMessages(roomId); return messages.map((text, i) => <div key={i}>{text}</div>) }
  • 66. class ChatPage extends Component { constructor() { super(); this.state = { messages: [] } this.onNewMessage = this.onNewMessage. bind(this); } componentDidMount () { SocketClient. subscribeForNewMessages (this.props.roomId, this.onNewMessage ); } componentWillUnmount () { SocketClient. unsubscribe (this.props.roomId); } componentWillReceiveProps (nextProps ) { if (nextProps .roomId !== this.props.roomId) { this.setState ({ messages: [] }); SocketClient. unsubscribe (this.props.roomId); SocketClient. subscribeForNewMessages (nextProps .roomId, this.onNewMessage ); } } onNewMessage (message) { this.setState ({ messages: [...this.state.messages , message] }) } render() { return this.state.messages. map((text, i) => <div key={i}>{text}</div>) } } Remember how it used to look?28 lines vs. 5 with custom hook
  • 67. Custom Hooks allow us to.. ● Easily share code ● Keep our components clean and readable ● Use Hooks from npm packages
  • 68.
  • 69. Other hooks ● useReducer ● useCallback ● useMemo ● useImperativeMethods ● useLayoutEffect
  • 70. Memo
  • 71. React.memo PureComponent for function components import React, {memo} from 'react'; const MyComponent = props => { ... } export default memo(MyComponent); Introduced on React 16.6
  • 72. React.memo PureComponent for function components import React, {memo} from 'react'; const MyComponent = props => { ... } const areEqual = (prevProps, nextProps) => { ... } export default memo(MyComponent, areEqual); Introduced on React 16.6
  • 73. <MyComponent x={1} y={2}/> DOM render x=1 y=2 Memo Cache <MyComponent x={2} y={2}/> render x=2 y=2 <MyComponent x={2} y={3}/> 1 2 3 Rendering “MyComponent” with Memo x=1 y=2 x=2 y=2 areEqual = (prev, next) => prev.x === next.x
  • 75. Lazy Code-Splitting import React, { lazy } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent' )); const MyComponent = (props) => <div> <OtherComponent/> </div> Introduced on React 16.6
  • 76. Lazy Code-Splitting import React, { lazy } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); const MyComponent = (props) => <div> <OtherComponent/> </div> Introduced on React 16.6
  • 77. Lazy Code-Splitting import React, { lazy } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent' )); const MyComponent = (props) => <div> <OtherComponent/> </div> Introduced on React 16.6
  • 78. Lazy Code-Splitting import React, { lazy } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); const MyComponent = (props) => <div> <OtherComponent/> </div> Introduced on React 16.6
  • 79. Lazy + Suspense Code-Splitting import React, { lazy, Suspense } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent' )); const MyComponent = (props) => <div> <Suspense fallback={<div>Loading..</div>}> <OtherComponent /> </Suspense> </div> Introduced on React 16.6
  • 80. Lazy + Suspense Code-Splitting import React, { lazy, Suspense } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); const MyComponent = (props) => <div> <Suspense fallback ={<div>Loading..</div>}> <OtherComponent /> </Suspense> </div> Introduced on React 16.6
  • 81. Lazy + Suspense Code-Splitting import React, { lazy, Suspense } from 'react'; const OtherComponent = React.lazy(() => import('./OtherComponent')); const MyComponent = (props) => <div> <Suspense fallback={<div>Loading..</div>}> <OtherComponent /> </Suspense> </div> Introduced on React 16.6
  • 82. const Home = lazy(() => import('./components/Home )); const Posts = lazy(() => import('./components/Posts' )); const App = () => ( <Router> <Suspense fallback={<Loading />}> <Switch> <Route exact path="/" component={Home} /> <Route path="/posts" component={Posts} /> </Switch> </Suspense> </Router> )
  • 83.
  • 84. Hook me up with Questions nirsky Nir_Hadassi