873 Matching Annotations
  1. Last 7 days
  2. Jul 2022
    1. this.handleChange

      change事件更新state,也就是用户输入的value,这就是受控组件

    2. this.state.value

      value随用户输入而改变state

    1. 想要将一个 React 元素渲染到根 DOM 节点中,只需把它们一起传入 ReactDOM.createRoot(): const root = ReactDOM.createRoot( document.getElementById('root') ); const element = <h1>Hello, world</h1>; root.render(element);

      createRoot()返回一个ReactDOM对象,该对象具有render方法。

    1. React may batch multiple setState() calls into a single update for better performance.

      so its not an actual race condition b/w two parallel instructions, but rather just a result of an optimisation performed by react

  3. Jun 2022
    1. If the component wrapped with memo re-renders, it means that one of its properties changes.
  4. May 2022
    1. React Helmet

      ```js import {Helmet} from "react-helmet";

      const Demo = props => ( <br /> <div className="application"> <Helmet> <script src="/path/to/resource.js" type="text/javascript" /> </Helmet> ... </div>

      ); ```

      DOM Method

      ```js componentDidMount () { const script = document.createElement("script"); script.src = "/path/to/resource.js"; script.async = true; document.body.appendChild(script); }

      export const appendScript = (scriptToAppend) => { const script = document.createElement("script"); script.src = scriptToAppend; script.async = true; document.body.appendChild(script); }

      class Demo extends React.Component { componentDidMount () { appendScript("/path/to/resource.js"); } } ```

      React Hooks

      js useEffect(() => { const script = document.createElement('script'); script.src = "/path/to/resource.js"; script.async = true; document.body.appendChild(script); return () => { document.body.removeChild(script); } }, []);

      ```js import { useEffect } from 'react'; const importScript = resourceUrl=> { useEffect(() => { const script = document.createElement('script'); script.src = resourceUrl; script.async = true; document.body.appendChild(script); return () => { document.body.removeChild(script); } }, [resourceUrl]); };

      const Demo = props => { importScript("/path/to/resource.js"); } ```

  5. Mar 2022
  6. Feb 2022
    1. js queryClient .getQueryCache() .findAll(['partial', 'key']) .forEach(({ queryKey }) => { queryClient.setQueryData(queryKey, newData) })

    1. However there are some restrictions: if you are going to use different URLs for GET/PATCH, for example, you have to use the same key, otherwise, React Query will not be able to match these queries.

      It is ok to use url as key for React query

  7. Jan 2022
    1. Routen, A., O’Mahoney, L., Ayoubkhani, D., Banerjee, A., Brightling, C., Calvert, M., Chaturvedi, N., Diamond, I., Eggo, R., Elliott, P., Evans, R. A., Haroon, S., Herret, E., O’Hara, M. E., Shafran, R., Stanborough, J., Stephenson, T., Sterne, J., Ward, H., & Khunti, K. (2022). Understanding and tracking the impact of long COVID in the United Kingdom. Nature Medicine, 28(1), 11–15. https://doi.org/10.1038/s41591-021-01591-4

    1. In previous technologies, the development for different devises were handled via different teams due to which there were gaps witnessed in the applications.
    1. Chadeau-Hyam, M., Wang, H., Eales, O., Haw, D., Bodinier, B., Whitaker, M., Walters, C. E., Ainslie, K. E. C., Atchison, C., Fronterre, C., Diggle, P. J., Page, A. J., Trotter, A. J., Ashby, D., Barclay, W., Taylor, G., Cooke, G., Ward, H., Darzi, A., … Elliott, P. (2022). SARS-CoV-2 infection and vaccine effectiveness in England (REACT-1): A series of cross-sectional random community surveys. The Lancet Respiratory Medicine, 0(0). https://doi.org/10.1016/S2213-2600(21)00542-7

    1. Instead of render props, we use Svelte's slot props: // React version <Listbox.Button> {({open, disabled} => /* Something using open and disabled */)} </Listbox.Button> <!--- Svelte version ---> <ListboxButton let:open let:disabled> <!--- Something using open and disabled ---> </ListboxButton>
    1. Data Transformation

      […]

      3. using the select option

      v3 introduced built-in selectors, which can also be used to transform data:

      /* select-transformation */
      
      export const useTodosQuery = () =>
        useQuery(['todos'], fetchTodos, {
          select: (data) => data.map((todo) => todo.name.toUpperCase()),
        })
      

      selectors will only be called if data exists, so you don't have to care about undefined here. Selectors like the one above will also run on every render, because the functional identity changes (it's an inline function). If your transformation is expensive, you can memoize it either with useCallback, or by extracting it to a stable function reference:

      /* select-memoizations */
      
      const transformTodoNames = (data: Todos) =>
        data.map((todo) => todo.name.toUpperCase())
      export const useTodosQuery = () =>
        useQuery(['todos'], fetchTodos, {
          // ✅ uses a stable function reference
          select: transformTodoNames,
        })
      
      export const useTodosQuery = () =>
        useQuery(['todos'], fetchTodos, {
          // ✅ memoizes with useCallback
          select: React.useCallback(
            (data: Todos) => data.map((todo) => todo.name.toUpperCase()),
            []
          ),
        })
      

      Further, the select option can also be used to subscribe to only parts of the data. This is what makes this approach truly unique. Consider the following example:

      /* select-partial-subscriptions */
      
      export const useTodosQuery = (select) =>
        useQuery(['todos'], fetchTodos, { select })
      
      export const useTodosCount = () => useTodosQuery((data) => data.length)
      
      export const useTodo = (id) =>
        useTodosQuery((data) =>
          data.find((todo) => todo.id === id))
      

      Here, we've created a useSelector like API by passing a custom selector to our useTodosQuery. The custom hooks still works like before, as select will be undefined if you don't pass it, so the whole state will be returned.

      But if you pass a selector, you are now only subscribed to the result of the selector function. This is quite powerful, because it means that even if we update the name of a todo, our component that only subscribes to the count via useTodosCount will not rerender. The count hasn't changed, so react-query can choose to not inform this observer about the update 🥳 (Please note that this is a bit simplified here and technically not entirely true - I will talk in more detail about render optimizations in Part 3).

      • 🟢 best optimizations
      • 🟢 allows for partial subscriptions
      • 🟡 structure can be different for every observer
      • 🟡 structural sharing is performed twice (I will also talk about this in more detail in Part 3)
    2. Data Transformation

      [...]

      2. In the render function

      As advised in Part 1, if you create custom hooks, you can easily do transformations there:

      /* render-transformation */
      
      const fetchTodos = async (): Promise<Todos> => {
        const response = await axios.get('todos')
        return response.data
      }
      
      export const useTodosQuery = () => {
        const queryInfo = useQuery(['todos'], fetchTodos)
        return {
          ...queryInfo,
          data: queryInfo.data?.map((todo) =>
            todo.name.toUpperCase()),
        }
      }
      

      As it stands, this will not only run every time your fetch function runs, but actually on every render (even those that do not involve data fetching). This is likely not a problem at all, but if it is, you can optimize with useMemo. Be careful to define your dependencies as narrow as possible. data inside the queryInfo will be referentially stable unless something really changed (in which case you want to recompute your transformation), but the queryInfo itself will not. If you add queryInfo as your dependency, the transformation will again run on every render:

      /* useMemo-dependencies */
      
      export const useTodosQuery = () => {
        const queryInfo = useQuery(['todos'], fetchTodos)
        return {
          ...queryInfo,
          // 🚨 don't do this - the useMemo does nothing at all here!
          data: React.useMemo(
            () => queryInfo.data?.map((todo) => todo.name.toUpperCase()),
            [queryInfo]
          ),
          // ✅ correctly memoizes by queryInfo.data
          data: React.useMemo(
            () => queryInfo.data?.map((todo) => todo.name.toUpperCase()),
            [queryInfo.data]
          ),
        }
      }
      

      Especially if you have additional logic in your custom hook to combine with your data transformation, this is a good option. Be aware that data can be potentially undefined, so use optional chaining when working with it.

      • 🟢 optimizable via useMemo
      • 🟡 exact structure cannot be inspected in the devtools
      • 🔴 a bit more convoluted syntax
      • 🔴 data can be potentially undefined
    1. 🤔 So what?

      Let’s review a typical Redux process for a fetch operation:

      1. Dispatch an Action fetchSomething() from within the Component
      2. This Action hits the Reducer which will update the store with something like isLoading: true
      3. The Component re-renders and displays a loader
      4. In the meanwhile the Action hits the Middleware which takes care of calling the API
      5. The API returns the response to the Middleware, which dispatches another Action: fetchSomethingSucceeded() when succeeded, or fetchSomethingFailed() when failed
      6. The succeeded/failed Action hits the Reducer, which updates the store
      7. Finally, the response is back to the Component (optionally through a memoized selector) which will show the data

      It’s a long process for just a simple fetch, isn’t it?

  8. Dec 2021
    1. Increasing StaleTime

      React Query comes with a default staleTime of zero. This means that every query will be immediately considered as stale, which means it will refetch when a new subscriber mounts or when the user refocuses the window. It is aimed to keep your data as up-to-date as necessary.

      This goal overlaps a lot with WebSockets, which update your data in real-time. Why would I need to refetch at all if I just manually invalidated because the server just told me to do so via a dedicated message?

      So if you update all your data via websockets anyways, consider setting a high staleTime. In my example, I just used Infinity. This means the data will be fetched initially via useQuery, and then always come from the cache. Refetching only happens via the explicit query invalidation.

      You can best achieve this by setting global query defaults when creating the QueryClient:

      const queryClient = new QueryClient({
        defaultOptions: {
          queries: {
            staleTime: Infinity,
          },
        },
      })
      
  9. Nov 2021
    1. { target: { value } }

      This might seem confusing at first glance. However this is just simple "nested destructruing" and "smart function parameters" used together

      Read the "Nested Destructuring" and "Smart Function Parameters" sections from the link below to get a better idea of what's going on.

      https://javascript.info/destructuring-assignment#object-destructuring

      the set() function can also be written as -----

      let set = (name) => {
          return ( (e) => {
              setDetails( {...details , [ name ] : e.target.value });
              console.log(details);
          })
      }
      

      notice how the predeclared variable name is being used as a key in the object. { [name] : value } NOT { name : value}. Skipping the box brackets will throw you an error This is because name is actually a variable. Similar to the way in which we use object[key] = value; notation to add a k-v pair, we have to use { [name] : value } ie. enclose the variable name in square brackets while creating an object using object literal syntax to make sure that the code works

  10. Oct 2021
  11. Sep 2021
    1. redux-thunk does: it is a middleware that looks at every action that passes through the system, and if it’s a function, it calls that function.
  12. Aug 2021
    1. All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes
    1. It's time to put some of these pieces together. We know that: Calling setState() queues a render of that component React recursively renders nested components by default Context providers are given a value by the component that renders them That value normally comes from that parent component's state This means that by default, any state update to a parent component that renders a context provider will cause all of its descendants to re-render anyway, regardless of whether they read the context value or not!.
    2. Immutability and Rerendering 🔗︎

      This section is gold to use as a teaching example

    3. All of these approaches use a comparison technique called "shallow equality". This means checking every individual field in two different objects, and seeing if any of the contents of the objects are a different value. In other words, obj1.a === obj2.a && obj1.b === obj2.b && ......... This is typically a fast process, because === comparisons are very simple for the JS engine to do. So, these three approaches do the equivalent of const shouldRender = !shallowEqual(newProps, prevProps).
    4. When trying to improve software performance in general, there are two basic approaches: 1) do the same work faster, and 2) do less work. Optimizing React rendering is primarily about doing less work by skipping rendering components when appropriate.
    5. After it has collected the render output from the entire component tree, React will diff the new tree of objects (frequently referred to as the "virtual DOM"), and collects a list of all the changes that need to be applied to make the real DOM look like the current desired output. The diffing and calculation process is known as "reconciliation".
    1. Here’s where immutability comes in: if you’re passing props into a PureComponent, you have to make sure that those props are updated in an immutable way. That means, if they’re objects or arrays, you’ve gotta replace the entire value with a new (modified) object or array. Just like with Bob – kill it off and replace it with a clone. If you modify the internals of an object or array – by changing a property, or pushing a new item, or even modifying an item inside an array – then the object or array is referentially equal to its old self, and a PureComponent will not notice that it has changed, and will not re-render. Weird rendering bugs will ensue.
    2. An easy way to optimize a React component for performance is to make it a class, and make it extend React.PureComponent instead of React.Component. This way, the component will only re-render if its state is changed or if its props have changed. It will no longer mindlessly re-render every single time its parent re-renders; it will ONLY re-render if one of its props has changed since the last render.
    1. connect is pure connect automatically makes connected components “pure,” meaning they will only re-render when their props change – a.k.a. when their slice of the Redux state changes. This prevents needless re-renders and keeps your app running fast.
    1. My personal summary is that new context is ready to be used for low frequency unlikely updates (like locale/theme). It's also good to use it in the same way as old context was used. I.e. for static values and then propagate updates through subscriptions. It's not ready to be used as a replacement for all Flux-like state propagation.
    2. One problem with the "Context vs Redux" discussions is that people often actually mean "I'm using useReducer to manage my state, and Context to pass down that value". But, they never state that explicitly - they just say "I'm using Context". That's a common cause of the confusion I see, and it's really unfortunate because it helps perpetuate the idea that Context "manages state"
    3. We can even say that server caching tools like React-Query, SWR, Apollo, and Urql fit the definition of "state management" - they store initial values based on the fetched data, return the current value via their hooks, allow updates via "server mutations", and notify of changes via re-rendering the component
    4. createContext() was designed to solve that problem, so that any update to a value will be seen in child components even if a component in the middle skips rendering.
    1. The Redux FAQ has some rules of thumb to help decide whether state should go in Redux, or stay in a component.In addition, if you separate your state by domain (by having multiple domain-specific contexts), then the problem is less pronounced as well.
    2. but in a more practical scenario, you often suffer from "death by a thousand cuts" which means that there's not really a single place that's slow, so you wind up applying React.memo everywhere. And when you do that, you have to start using useMemo and useCallback everywhere as well (otherwise you undo all the work you put into React.memo). Each of these optimizations together may solve the problem, but it drastically increases the complexity of your application's code and it actually is less effective at solving the problem than colocating state because React does still need to run through every component from the top to determine whether it should re-render. You'll definitely be running more code with this approach, there's no way around that.
    1. I consistently see developers putting all of their state into redux. Not just global application state, but local state as well. This leads to a lot of problems, not the least of which is that when you're maintaining any state interaction, it involves interacting with reducers, action creators/types, and dispatch calls, which ultimately results in having to open many files and trace through the code in your head to figure out what's happening and what impact it has on the rest of the codebase.
    1. How to Make a React Progressive Web Application (PWA)Eugene VolkovFrontend DeveloperKate KikidzhanCloud & SaaS Product ResearcherReactJavaScriptPWAHomeBlogDevelopmentHow to Make a React Progressive Web Application (PWA)Oct 7, 202021 min readThe early bird catches the worm. But the situation was not so favourable back in 2007 when Steve Jobs proposed the idea of web applications to be the model for iPhone Apps. Back then, the tech community was not yet ready to bring a huge interest in web apps. But since 2015, tech giants like Google and Microsoft have been preparing the tech ground for progressive web apps (or simply – PWAs). And now, PWA became a must-have technology for both giant corporations and small startups. Twitter, Starbucks, Google, and Aliexpress use progressive web apps to boost their online presence. At Codica, we have been helping our customers to develop their businesses by building robust PWA for our customers since 2015. That is why we have created this comprehensive guide on how to create a PWA with React. Also, you will see the most prominent progressive web app examples.

      The early bird catches the worm. But the situation was not so favourable back in 2007 when Steve Jobs proposed the idea of web applications to be the model for iPhone Apps. Back then, the tech community was not yet ready to bring a huge interest in web apps.

      But since 2015, tech giants like Google and Microsoft have been preparing the tech ground for progressive web apps (or simply – PWAs). And now, PWA became a must-have technology for both giant corporations and small startups. Twitter, Starbucks, Google, and Aliexpress use progressive web apps to boost their online presence.

      At Codica, we have been helping our customers to develop their businesses by building robust PWA for our customers since 2015. That is why we have created this comprehensive guide on how to create a PWA with React. Also, you will see the most prominent progressive web app examples.

  13. Jul 2021
    1. Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

      I like this definition of 'components'.

  14. Jun 2021
    1. The ecosystem behind React gave you too many choices of this sort, which fragmented the tech stack and caused the infamous “Javascript fatigue”.

      To me, the reason React ruined web development is because it homogenized & centralized the practice, in an abstraction that is decoupled & non-interoperable with other techniques & styles.

      The author is arguing that React didn't centralize enough, but to me, it sucked all the oxygen out of the diverse interesting place that was web development. That it didn't try to solve all problems in the stack is, if anything, a most relief. It succeeded because it didn't bundle in a data-layer. It succeeded because it didn't bundle in state. It succeeded because it didn't bundle in routing. Each of these areas have evolved independently & seen great strides across the last half decade. That's a huge win, that's why React is so strong: because it didn't try to form opinions.

      Alas React itself implies a strong opinion, has a big abstraction that de-empowers & de-inter-operates with the DOM, that keeps it from working in concert with any other technology. It has enormous diversity, but only under it's own umbrella. It has crushed a much livelier sporting aspect of web development.

      I'm so tired of weenies complaining about fragmentation. Get lost and fuck off. This medium is flexible & diverse & interesting. Stop applying your industrial software want, your software authoritarianism, "why can't everyone just do it my way/the right way" horse shit. Such a shitty attitude, from people selling FUD & clutching at the idea that everyone's gonna be happy & productive if we can just make the right framework. How uncreative & droll.

  15. Mar 2021
    1. React and Svelte are very similar in many ways, but what I've found is that in all the little ways that they are different, I prefer Svelte.
    2. If I were to sum up why in one sentence, it's because I don't miss useEffect. I understand why it exists, I understand the approach React takes, and there are benefits of its approach. But writing complex React components feels more like admin; a constant worry that I'll miss a dependency in my useEffect call and end up crashing my browser session. With Svelte I don't have that lingering feeling, and that's what I've come to enjoy.
    3. One gripe I've had with this approach is that you lose the visual cues that you're passing children into the Box component; they now aren't nested within the Box when you render them like we're used to in HTML; it's now up to you to read the props and spot which ones are being used to provide children.
    4. Svelte is different in that by default most of your code is only going to run once; a console.log('foo') line in a component will only run when that component is first rendered.
    5. Here's where I start to have a preference for Svelte; the two are very similar but once I got used to Svelte I found that React felt like jumping through hoops. You can't create a worker instance, it has to go in a useRef, and then you can't easily pull code out into a function without then requiring useCallback so it can be a safe dependency on useEffect. With Svelte I write code that's closer to "plain" JavaScript, whereas in React more of my code is wrapped in a React primitive.
    6. One part of React that I've always championed is how it's just JavaScript. I like that in React you don't use a distinct template syntax and instead embed JavaScript, compared to Svelte's templating language
    7. I will always find React's approach easier - at least in my head - and I think more friendly to people familiar with JavaScript who are learning a library.
    8. because React components are re-executed every time the component re-renders, you can easily end up with thousands of workers being created! It's essential to use useRef to avoid this problem by maintaining a reference to the worker that you've created.
    9. Talking of context, that's much closer to the approach I take with Svelte and use a writable store.
    1. 副作用内からなぜ関数を返したのか? これこそが副作用のクリーンアップのためのオプションの仕組みです。すべての副作用は、それをクリーンアップするための関数を返すことができます。これにより購読を開始するためのロジックと解除するためのロジックを並べて書くことができます。両方とも同じ副作用の一部なのです! React は具体的には副作用のクリーンアップをいつ発生させるのか? React はコンポーネントがアンマウントされるときにクリーンアップを実行します。しかし、すでに学んだ通り、副作用は 1 回だけでなく毎回のレンダー時に実行されます。このため React は、ひとつ前のレンダーによる副作用を、次回の副作用を実行する前にもクリーンアップします。この後で、これがなぜバグの回避につながるのか、そしてこれがパフォーマンスの問題を引き起こしている場合にどのようにしてこの挙動を止めるのかについて説明します。 補足 副作用から名前付きの関数を返す必要はありません。ここでは目的を明示するために cleanup という名前にしましたが、アロー関数を返すことも別の名前を付けることも可能です。 まとめ useEffect を用いることで、コンポーネントのレンダー後に実行される様々な種類の副作用を表現できることを学びました。いくつかの副作用はクリーンアップが必要である可能性があり、その場合は関数を返します: useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); クリーンアップフェーズが必要ない副作用もあり、その場合は何も返す必要はありません。 useEffect(() => { document.title = `You clicked ${count} times`; }); 副作用フックは両方のユースケースをひとつの API に統合します。 副作用フックの動作について十分わかったと感じる場合や、逆にもううんざりだという場合は、ここで次のページ(フックのルールについて)に進んでも構いません。 副作用を使う場合のヒント このページの残りの部分では、経験のある React 利用者が興味を持つかもしれない useEffect の深い概念について説明します。今すぐ読み進める必要があるとは思わないでください。副作用フックについて詳細が知りたくなったらいつでもこのページに戻ってくればいいのです。 ヒント:関心を分離するために複数の副作用を使う フックを導入する動機のページで述べた問題のひとつは、しばしばそれぞれのライフサイクルメソッドに関連のないロジックが含まれ、一方で関連するロジックが複数のメソッドに分割されてしまう、ということです。以下に示すのは、これまでの例で挙げたカウンタとフレンド状態インジケータとを組み合わせたコンポーネントです。 class FriendStatusWithCounter extends React.Component { constructor(props) { super(props); this.state = { count: 0, isOnline: null }; this.handleStatusChange = this.handleStatusChange.bind(this); } componentDidMount() { document.title = `You clicked ${this.state.count} times`; ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); } handleStatusChange(status) { this.setState({ isOnline: status.isOnline }); } // ... ここで、document.title を設定するためのロジックが componentDidMount と componentDidUpdate に分離してしまっていることに注意してください。データ購読のためのロジックもやはり componentDidMount と componentWillUnmount とに分離しています。そして componentDidMount には両方の仕事のためのコードが含まれています。 ではフックはどのようにこの問題を解決するのでしょうか? ステートフックを複数回呼べるのと同様の方法で、副作用を複数回利用することができます。このため、互いに関係のないロジックは別の副作用に分離することが可能です。 function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); // ... } フックを使うことで、ライフサイクルのメソッド名に基づくのではなく、実際に何をやっているのかに基づいてコードを分割できます。React はコンポーネントで利用されているすべての副作用を、指定されている順番で適用していきます。 解説:なぜ副作用は毎回の更新ごとに実行されるのか クラスに慣れていれば、なぜクリーンアップフェーズは、アンマウント時の 1 度だけではなく再レンダー時に毎回発生するのか、と不思議に思っているかもしれません。実践的な例で、この設計によりなぜバグの少ないコンポーネントが作れるようになるのか見てみましょう。 このページの前の部分で、フレンドがオンラインかどうかを表示する FriendStatus コンポーネントの例を示しました。このクラスでは this.props の中にある friend.id を参照して、コンポーネントがマウントした後にフレンドのステータスを購読し、アンマウント時には購読を解除します: componentDidMount() { ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); } ですがコンポーネントが表示されている最中に friend プロパティが変わったらどうなるのでしょうか? このコンポーネントは間違ったフレンドのオンラインステータスを表示し続けてしまいます。これはバグです。しかも誤ったフレンド ID を使って購読解除を呼び出してしまうため、アンマウント時にメモリリークやクラッシュを引き起こしてしまうでしょう。 クラスコンポーネントの場合は、このようなケースに対処するために componentDidUpdate を加える必要がありました。 componentDidMount() { ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentDidUpdate(prevProps) { // Unsubscribe from the previous friend.id ChatAPI.unsubscribeFromFriendStatus( prevProps.friend.id, this.handleStatusChange ); // Subscribe to the next friend.id ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); } 適切な componentDidUpdate 処理をし忘れることが、React アプリケーションにおけるよくあるバグの原因となっていました。 ではこのコンポーネントのフックを利用したバージョンを見てみましょう。 function FriendStatus(props) { // ... useEffect(() => { // ... ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); 動作は変わっておらず、前述のバグも起こらなくなります。 useEffect はデフォルトで更新を処理するため、更新のための特別なコードは不要です。新しい副作用を適用する前に、ひとつ前の副作用をクリーンアップします。これを例示するため、このコンポーネントが経時的に発生させる可能性のある購読登録と購読解除のシーケンスを示します: // Mount with { friend: { id: 100 } } props ChatAPI.subscribeToFriendStatus(100, handleStatusChange); // Run first effect // Update with { friend: { id: 200 } } props ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // Clean up previous effect ChatAPI.subscribeToFriendStatus(200, handleStatusChange); // Run next effect // Update with { friend: { id: 300 } } props ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // Clean up previous effect ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // Run next effect // Unmount ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // Clean up last effect この挙動によりデフォルトで一貫性を保証することができ、クラスコンポーネントでよく見られた更新ロジック書き忘れによるバグを防止することができます。 ヒント:副作用のスキップによるパフォーマンス改善 いくつかの場合では、副作用のクリーンアップと適用とをレンダーごとに毎回行うことはパフォーマンスの問題を引き起こす可能性があります。クラスコンポーネントの場合、この問題は componentDidUpdate の内部で prevProps や prevState と比較するコードを加えることで解決できました。 componentDidUpdate(prevProps, prevState) { if (prevState.count !== this.state.count) { document.title = `You clicked ${this.state.count} times`; } } これはよくある要求なので、useEffect フックの API にはこの動作が組み込まれています。再レンダー間で特定の値が変わっていない場合には副作用の適用をスキップするよう、React に伝えることができるのです。そのためには、useEffect のオプションの第 2 引数として配列を渡してください。 useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // Only re-run the effect if count changes 上記の例では、第 2 引数として [count] を渡しています。どういう意味でしょうか? もし count が 5 で、次回のコンポーネントのレンダー時にも count がまだ 5 であった場合、React は前回のレンダー時に覚えておいた [5] と今回のレンダーの [5] とを比較します。配列内のすべての要素が同一 (5 === 5) ですので、React は副作用をスキップします。これが最適化です。 再レンダー時に count が 6 に変更されている場合、前回レンダー時に覚えておいた [5] と今回のレンダー時の [6] という配列とを比較します。今回は 5 !== 6 ですので React は副作用を再適用します。配列内に複数の要素がある場合、React は配列内の要素のうちひとつでも変わっている場合に副作用を再実行します。 クリーンアップフェーズがある副作用でも同様に動作します: useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }, [props.friend.id]); // Only re-subscribe if props.friend.id changes 将来的には、ビルド時の変換で第 2 引数を自動で加えられるようになるかもしれません。 補足 この最適化を利用する場合、時間の経過とともに変化し副作用によって利用される、コンポーネントスコープの値(props や state など)がすべて配列に含まれていることを確認してください。さもないとあなたのコードは以前のレンダー時の古い値を参照してしまうことになります。その他の最適化のオプションについてはフック API リファレンスで説明しています。 もしも副作用とそのクリーンアップを 1 度だけ(マウント時とアンマウント時にのみ)実行したいという場合、空の配列 ([]) を第 2 引数として渡すことができます。こうすることで、あなたの副作用は props や state の値のいずれにも依存していないため再実行する必要が一切ない、ということを React に伝えることができます。これは特別なケースとして処理されているわけではなく、依存配列を普通に処理すればそうなるというだけの話です。 空の配列 ([]) を渡した場合、副作用内では props と state の値は常にその初期値のままになります。[] を渡すことはおなじみの componentDidMount と componentWillUnmount による概念と似ているように感じるでしょうが、通常はこちらやこちらのように、副作用を過度に再実行しないためのよりよい解決方法があります。また useEffect はブラウザが描画し終えた後まで遅延されますので、追加の作業をしてもそれほど問題にならないということもお忘れなく。 eslint-plugin-react-hooks パッケージの exhaustive-deps ルールを有効にすることをお勧めします。これは依存の配列が正しく記述されていない場合に警告し、修正を提案します。 次のステップ おめでとうございます! 長いページでしたが、最終的に副作用に関するほとんどの疑問が解決していることを望みます。これでステートフックと副作用フックの両方を学んだので、それらを組み合わせてやれることがたくさんあります。クラスコンポーネントにおけるほとんどのユースケースがカバーされていますが、足りない部分については他のフックが役立つかもしれません。 また、動機のところで述べた問題をフックがどのように解決するのかについてもわかり始めてきたでしょう。副作用のクリーンアップがどのようにして componentDidUpdate と componentWillUnmount との間でのコードの重複を防ぎ、関係したコードを並べて書くことができるようにし、バグの少ないコードを記述できるようにするのかを見てきました。また目的別に副作用を分割する方法も学びましたが、これはクラスでは全く不可能なことでした。 この時点で、一体フックがどのように動作しているのか疑問に感じているかもしれません。useState のそれぞれの呼び出しがどの state 変数に対応しているのかを、React はどのようにして知るのでしょうか? 更新のたびに、前回と今回の副作用とを React はどのように対応付けるのでしょうか? 次のページではフックのルールについて学びます — このルールはフックが動作するために必須のものです。Is this page useful?このページを編集する

      useEffectで返されている関数は、 クラスコンポーネントにおけるcomponentWillUnmountの部分に実装する処理を書く部分だと理解しておけば良さそう。 つまり、コンポーネントがアンマウントされるときに実行される

    1. What are the current trends in JavaScript development?

      Performance, speed, or popularity? What are the most vital characteristics that developers seek in the tech stack? There could hardly be a single reason why certain frameworks rise, while others become the thing of the past.

      What you can do is to observe the driving directions within the front-end landscape. So let’s dive into the top JavaScript trends to watch in 2021.

  16. Feb 2021
    1. Next.js gives you the best developer experience with all the features you need for production: hybrid static & server rendering, TypeScript support, smart bundling, route pre-fetching, and more. No config needed.

  17. Jan 2021
  18. Dec 2020
    1. React abstracts the DOM with functionally pure declarative rendering and provides escape hatches back to mutable imperative DOM land. This is a profound philosophical difference that Rich gave a talk about.
    2. It's true that Svelte does not allow you to map over children like React, but its slot API and <svelte:component> provide similarly powerful composition. You can pass component constructors as props and instantiate them with <svelte:component>, and use slots and their let bindings for higher order composition. It sounds like you're thinking in virtual DOM idioms instead of Svelte's.
    3. My frustration is mainly from Svelte's choices that are very un-JavaScript-like. It doesn't have to be "like React/Vue". React is React because it doesn't restrict what you can do with JavaScript for the most part. It's just common FP practice to fold/map.
  19. Nov 2020
    1. In this world of digitization, it is essential that you bring your business to the online platforms. The fact is, React Native is one of the most emerging technologies for developing the best application for your business.

      React Native is one of the most emerging technologies for the business. Know how can you hire a React Native developer with less effort.

    1. For use$ since svelte is never going to support actions for components, i designed something that reminds React hooks that will in some ways replace this feature.

      Isn't that what use$ is trying to do already? How is that "something that reminds React hooks" any different? Will be interested to see...