iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
Modern Web

React 走出新手村 系列 第 18

React 走出新手村 — 在組件裡犯的錯(II)

  • 分享至 

  • xImage
  •  

前言

今天我們接續前一篇的案例,再來講講一些NG的案例,總是會有一些講不聽不想拆 component 的人,在新版本的環境下應該會被強制修改,因為如果不改的話會被重置 state,我們看個簡單的範例:

import React, { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const onAdd = () => setCount(count + 1);
  const onMin = () => setCount(count - 1);
  // 把他塞回來
  const TxtInput = () => {
    const [val, setVal] = useState("");
    const txtChange = (e) => setVal(e.target.value);
    return (
      <>
        <input value={val} onChange={txtChange} />
      </>
    );
  };
  return (
    <div className="App">
      <div style={{ display: "flex", justifyContent: "center" }}>
        <button
          onClick={onMin}
          style={{ border: 0, borderRadius: "10px", margin: 4, width: 40 }}
        >
          -
        </button>
        <p>{count}</p>
        <button
          onClick={onAdd}
          style={{ border: 0, borderRadius: "10px", margin: 4, width: 40 }}
        >
          +
        </button>
      </div>
      <TxtInput />
    </div>
  );
}

然後你來到畫面操作,如下:
https://ithelp.ithome.com.tw/upload/images/20230917/20129020wEI04vWSEe.png
先在輸入框輸入字元
https://ithelp.ithome.com.tw/upload/images/20230917/20129020FRJnKkUJYw.png
觸發任意上方按鈕
https://ithelp.ithome.com.tw/upload/images/20230917/20129020OAxl8rxEdJ.png

原因

這是因為batch updating的問題所造成的,要解決這樣的問題只要簡單地將 TxtInput 移到外面就好了,如下:

import React, { useState } from "react";
// 把它拆出來,目的是不要讓他和其他的組件混到生命週期
const TxtInput = () => {
  const [val, setVal] = useState("");
  const txtChange = (e) => setVal(e.target.value);
  return (
    <>
      <input value={val} onChange={txtChange} />
    </>
  );
};

export default function App() {
  const [count, setCount] = useState(0);
  const onAdd = () => setCount(count + 1);
  const onMin = () => setCount(count - 1);
  
  return (
    <div className="App">
      <div style={{ display: "flex", justifyContent: "center" }}>
        <button
          onClick={onMin}
          style={{ border: 0, borderRadius: "10px", margin: 4, width: 40 }}
        >
          -
        </button>
        <p>{count}</p>
        <button
          onClick={onAdd}
          style={{ border: 0, borderRadius: "10px", margin: 4, width: 40 }}
        >
          +
        </button>
      </div>
      <TxtInput />
    </div>
  );
}

這就是為什麼不建議在 component 裡面塞 component 的原因,因為你沒有處理 memo 或是用 useCallback 去封包,那它就是會被當成是新的 refference 去處理。

解決方法

那如果要在裡面處理的話就要加入 useEffect 去判斷,這裡正常人的選擇應該還是簡單拆分出去就好,所以要養成拆組件的習慣,然後要知道為何而拆可以參考我之前的文章

總結

希望這次的分享,能讓大家更認知到什麼是我們應該要盡量避免的作法,同時有解答到你們剛好發生錯誤的瞬間。

錯誤就是錯誤,不是 coding style 的問題,而是對 jsx 及其運行方式不熟悉,因為現在以 jsx 為基礎做開發的框架,早就不止 React 一家了,相同的問題也會發生其他 jsx 新興的框架當中。

我遇過很多新手會找藉口來合理化自己懶惰的行為,讓自己活在『自己以為』的認知裡面,錯誤發生就怪框架、怪工具設計不好,但往往就忽略了自己錯誤的觀念使用習慣,這樣的狀態真的不好。

前端的問題不僅僅是靠框架,最重要的三元素仍然還是 Html/javascript/css,如同前面解釋過的底層概念一樣,整個 React 還是遵守 Javascript 本身的處理機制,當我們開發專案的時候也可以想一想:

如果把它當成是一般的 Javascript 我還會這樣處理嗎?還是會保持 Singleton pattern 的概念做整理呢?

給全新手的大禮包

React基本Hook教學


上一篇
React 走出新手村 — 在組件裡犯的錯(I)
下一篇
React 走出新手村 — 路由基礎
系列文
React 走出新手村 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言