├── .gitignore
├── README.md
├── images
├── useContext-app.png
├── useContext-themedbutton.png
├── useContext-toolbar.png
├── useEffect.png
├── useMemo.jpeg
├── useReducer.png
├── useRef.jpeg
└── useState.jpeg
├── use-callback
├── react
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── App.js
│ │ ├── ExpensiveToRenderButton.js
│ │ ├── expensive.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── svelte
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.png
│ ├── global.css
│ └── index.html
│ ├── rollup.config.js
│ ├── scripts
│ └── setupTypeScript.js
│ └── src
│ ├── App.svelte
│ ├── ExpensiveToRenderButton.svelte
│ ├── expensive.js
│ └── main.js
├── use-context
├── react
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── App.js
│ │ ├── ThemedButton.js
│ │ ├── Toolbar.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── svelte
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.png
│ ├── global.css
│ └── index.html
│ ├── rollup.config.js
│ ├── scripts
│ └── setupTypeScript.js
│ └── src
│ ├── App.svelte
│ ├── ThemedButton.svelte
│ ├── Toolbar.svelte
│ └── main.js
├── use-effect
├── react
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── Timer.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── svelte
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.png
│ ├── global.css
│ └── index.html
│ ├── rollup.config.js
│ ├── scripts
│ └── setupTypeScript.js
│ └── src
│ ├── Timer.svelte
│ └── main.js
├── use-memo
├── react
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── Fibonacci.js
│ │ ├── fib.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── svelte
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.png
│ ├── global.css
│ └── index.html
│ ├── rollup.config.js
│ ├── scripts
│ └── setupTypeScript.js
│ └── src
│ ├── Fibonacci.svelte
│ ├── fib.js
│ └── main.js
├── use-reducer
├── react
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── Counter.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── svelte
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.png
│ ├── global.css
│ └── index.html
│ ├── rollup.config.js
│ ├── scripts
│ └── setupTypeScript.js
│ └── src
│ ├── Counter.svelte
│ └── main.js
├── use-ref
├── react
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── TextInputWithFocusButton.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ └── yarn.lock
└── svelte
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.png
│ ├── global.css
│ └── index.html
│ ├── rollup.config.js
│ ├── scripts
│ └── setupTypeScript.js
│ └── src
│ ├── TextInputWithFocusButton.svelte
│ └── main.js
└── use-state
├── react
├── .gitignore
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── Counter.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── serviceWorker.js
│ └── setupTests.js
└── yarn.lock
└── svelte
├── .eslintrc.js
├── .gitignore
├── README.md
├── package.json
├── public
├── favicon.png
├── global.css
└── index.html
├── rollup.config.js
├── scripts
└── setupTypeScript.js
└── src
├── Counter.svelte
└── main.js
/.gitignore:
--------------------------------------------------------------------------------
1 | public/build
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Hooks in Svelte
2 |
3 | [React Hook](https://reactjs.org/docs/hooks-intro.html) examples ported to [Svelte](https://svelte.dev).
4 |
5 | **New 📣**: [React ⇆ Svelte Cheatsheet](https://dev.to/joshnuss/react-to-svelte-cheatsheet-1a2a)
6 |
7 | # useState
8 |
9 | In Svelte, `const [varName, set] = useState(initialValue)` becomes `let varName = initialValue`. The setter function is replaced with JavaScript's assignment operator `=`.
10 |
11 | [React example](/use-state/react/src/Counter.js)
12 | [Svelte example](/use-state/svelte/src/Counter.svelte)
13 |
14 | 
15 |
16 | # useEffect
17 |
18 | In React, there are 3 ways to `useEffect()`.
19 |
20 | 1. With `null` dependencies: `useEffect(fn)`. This runs on every render.
21 | 2. With an empty array as dependencies: `useEffect(fn, [])`. This runs during mount, and cleanup function runs on unmount.
22 | 3. With a list of dependency vars: `useEffect(fn, [a, b, c])`. This reavaulates whenever a dependency changes. The cleanup runs whenever dependencies change and during unmount.
23 |
24 | This is an example of #2, where the callback runs when component is mounted and cleanup runs when unmounted.
25 |
26 | [React example](/use-effect/react/src/Timer.js)
27 | [Svelte example](/use-effect/svelte/src/Timer.svelte)
28 |
29 | 
30 |
31 | # useMemo
32 |
33 | [React example](/use-memo/react/src/Fibonacci.js)
34 | [Svelte example](/use-memo/svelte/src/Fibonacci.svelte)
35 |
36 | In Svelte, all reactive statements are memoized. Instead of `const var = useMemo(() => expression, dependencies)`, you can use `$: var = expression`. Notice that with Svelte, you don't need to declare the dependencies. The compiler infers them for you.
37 |
38 | 
39 |
40 | # useRef
41 |
42 | [React example](/use-ref/react/src/TextInputWithFocusButton.js)
43 | [Svelte example](/use-ref/svelte/src/TextInputWithFocusButton.svelte)
44 |
45 | In Svelte, `useRef()` is `bind:this`.
46 |
47 | 
48 |
49 | # useReducer
50 |
51 | [React example](/use-reducer/react/src/Counter.js)
52 | [Svelte example](/use-reducer/svelte/src/Counter.svelte)
53 |
54 | In Svelte, `useReducer()` can be replaced with a `writable()` store. Instead of dispatching using a `switch` statement, functions can be defined on the store directly.
55 |
56 | 
57 |
58 | # useCallback
59 |
60 | In React, `useCallback` is used to memoize functions. This is needed because event handlers are re-defined on every render.
61 |
62 | Take this example:
63 |
64 | ```js
65 | // This function (component) is executed on every render
66 | function Component() {
67 | // this event handler is redefined on every render
68 | const handleClick = () => alert("hello")
69 |
70 | // because `handleClick` is redefined on every render, `ChildComponent` will be re-rendered too. Because its `onClick` prop is considered changed.
71 | return
72 | }
73 | ```
74 |
75 | So we need to wrap `handleClick` in a `useCallback`, to give a hint to the rendering system that the handler wasn't changed.
76 |
77 | In Svelte this isn't needed, because event handlers are declared inside `
14 |
15 |
16 |
17 |
18 |