Hoang  Ha

Hoang Ha

1639380504

Tối ưu hóa quản lý trạng thái trong các ứng dụng React

Xây dựng giao diện người dùng luôn là một thách thức. Một trong những vấn đề cần giải quyết chính là quản lý nhà nước. Ứng dụng React không phải là một ngoại lệ. Khi Facebook công bố thư viện, chúng tôi đã coi nó là một lớp xem . Nhanh chóng sau đó, chúng tôi nhận ra rằng nó còn hơn thế nữa. Với luồng dữ liệu một hướng, React đã làm cho việc phát triển front-end trở nên dễ đoán và mạnh mẽ hơn một chút. Tuy nhiên, câu trả lời cho một câu hỏi quan trọng đã bị thiếu - “Chúng ta quản lý nhà nước như thế nào?”. Trong những năm qua, Facebook và cộng đồng React đã có nhiều loại giải pháp khác nhau. Trong bài viết này, chúng ta sẽ xem một số trong số chúng và sẽ đưa ra lời khuyên về thời điểm sử dụng chúng.

Bước đầu tiên để giải quyết vấn đề là xác định vấn đề

Quản lý nhà nước đã khó và càng khó hơn nếu chúng ta làm không đúng chỗ. Bước đầu tiên là xác định loại trạng thái mà chúng ta đang đối phó. Có nhiều loại khác nhau, và việc ủi loại nào chúng ta có là rất quan trọng đối với công cụ sau đó. Nếu chúng tôi đánh giá sai vào thời điểm này, chúng tôi sẽ kết thúc với một thiết lập không tối ưu. Vì vậy, trả lời câu hỏi "Cái gì sống ở đâu?" câu hỏi là quan trọng.

Tiểu bang địa phương

Một trạng thái chỉ tồn tại trong một thành phần duy nhất mà chúng tôi coi là cục bộ. Một ví dụ về điều đó là chức năng xem thêm. Hãy tưởng tượng chúng ta có một văn bản dài, nhưng chúng ta cắt bớt nó và hiển thị một liên kết nhỏ ở cuối. Nếu người dùng nhấp vào nó, chúng tôi sẽ tiết lộ nội dung. Chúng tôi cần một lá cờ cho chúng tôi biết liệu liên kết có được nhấn hay không.

function Text() {
  const [viewMore, setViewMore] = useState(false);

  return (
    <Fragment>
      <p>
        React makes it painless to create interactive UIs. 
        {
          viewMore && <span>
            Design simple views for each state in your application.
          </span>
        }
      </p>
      <button onClick={() => setViewMore(true)}>read more</button>
    </Fragment>
  );
}                                                                          

Việc sử dụng useStatetrong thành phần này là quản lý nhà nước của chúng tôi. Một kỹ thuật để xác định loại trạng thái này là hỏi ai cần biết về nó. Trong trường hợp này, nó chỉ là <Text>thành phần của chúng ta . Vì vậy, thật hợp lý khi tạo viewMorecờ ngay tại nơi chúng ta sẽ tiêu thụ giá trị.

Các vấn đề với nhà nước địa phương xảy ra rất thường xuyên khi chúng ta cố gắng quản lý quá nhiều thứ. Chúng tôi định vị trạng thái một cách chính xác, nhưng logic yêu cầu nhiều biến. Hãy xem xét ví dụ sau:

function ILoveCats() {
  const [cat, setCatURL] = useState(null);
  const [isLoading, setLoadingFlag] = useState(false);
  const [error, setError] = useState(null);

  async function getCat() {
    setLoadingFlag(true);
    try {
      const query = await fetch('https://api.thecatapi.com/v1/images/search');
      const [{ url }] = await query.json();
      setLoadingFlag(false);
      setCatURL(url);
    } catch(error) {
      setError(true)
    }
  }
  return (
    <>
      <button onClick={getCat}>I love cats</button>
      { error && 'Meow! Meow!'}
      { isLoading && 'Loading ...'}
      { cat && <img src={cat} /> }
    </>
  )
}                                         

Thành <ILoveCats>phần này cung cấp một tính năng hiển thị hình ảnh của một con mèo trên màn hình. Người dùng cần nhấn một nút và getCatchức năng này sẽ cung cấp URL của hình ảnh. Lưu ý cách chúng ta có ba biến để quản lý toàn bộ quá trình. Chúng tôi có một cái giữ URL, một cái khác cho chúng tôi biết yêu cầu có đang được thực hiện hay không và một cái thông báo lỗi. Chúng tôi có thể nghĩ đến một số trường hợp cạnh tranh khác, và chúng tôi có thể sẽ mang đến nhiều useStatephát biểu hơn . Trong trường hợp này, một trong những giải pháp khả thi là xem xét một cỗ máy trạng thái.

const STATES = {
  IDLE: 'IDLE',
  LOADING: 'LOADING',
  SUCCESS: 'SUCCESS',
  ERROR: 'ERROR'
}
function ILoveCats() {
  const [status, setStatus] = useState({ value: STATES.IDLE });

  async function getCat() {
    setStatus({ value: STATES.LOADING });
    try {
      const query = await fetch('https://api.thecatapi.com/v1/images/search');
      const [{ url }] = await query.json();
      setStatus({ value: STATES.SUCCESS, url });
    } catch(error) {
      setStatus({ value: STATES.ERROR });
    }
  }
  return (
    <>
      <button onClick={getCat}>I love cats</button>
      { status.value === STATES.ERROR && 'Meow! Meow!'}
      { status.value === STATES.LOADING  && 'Loading ...'}
      { status.value === STATES.SUCCESS  && <img src={status.url} /> }
    </>
  )
}   

Với phiên bản thành phần mới này, chúng tôi chỉ có một biến - status. Nó giữ tiến độ hiện tại của người dùng. Chúng ta có thể nói rất nhiều về máy trạng thái và lợi ích của chúng. Nếu bạn muốn khám phá khái niệm này, hãy nhớ xem XState . Chúng tôi phải làm rõ rằng chúng tôi đã không triển khai một máy trạng thái hoàn chỉnh. Chúng tôi không có định nghĩa chuyển đổi. Nhưng ngay cả khi không có điều đó, thành phần đọc tốt hơn và nó trở nên dễ dàng hơn để tuân theo logic.

Loại trạng thái tiếp theo mà chúng ta sẽ nói đến là kết hợp nhiều thành phần.

Trạng thái tính năng

Trạng thái tính năng là khi chúng ta có hai hoặc nhiều thành phần chia sẻ cùng một thông tin. Ví dụ về trạng thái như vậy là mọi biểu mẫu chứa nhiều đầu vào. Hãy minh họa bằng một ví dụ:

const Skill = ({ onChange }) => (
  <label> Skill:
    <input type="text" onChange={e => onChange(e.target.value)}/>
  </label>
);
const Years = ({ onChange }) => (
  <label> Years of experience:
    <input type="text" onChange={e => onChange(e.target.value)}/>
  </label>
);

function Form() {
  const [skill, setSkill] = useState('');
  const [years, setYears] = useState('');

  const isFormReady = skill !== '' && years !== '';

  return (
    <form>
      <Skill onChange={setSkill} />
      <Years onChange={setYears} />
      <button disabled={!isFormReady}>submit</button>
    </form>
  );
}                                 

Một biểu mẫu có hai đầu vào văn bản. Người dùng nhập giá trị vào cả hai trường. Chúng tôi tắt nút theo mặc định và chỉ bật nó khi chúng tôi có hai giá trị. Để ý xem chúng ta cần skillsyearsđóng từng cái như thế nào để có thể tính toán isFormReady. Thành <Form>phần là một nơi hoàn hảo để thực hiện logic như vậy vì nó bao bọc tất cả các đầu vào. Thường thì các thành phần như vậy quản lý một đối tượng dữ liệu có chứa tất cả thông tin biểu mẫu. Ví dụ này cho thấy ranh giới mỏng giữa tính năng và trạng thái ứng dụng (chúng ta sẽ thấy nó trong phần tiếp theo). Chúng tôi có thể dễ dàng đưa trạng thái đó vào cửa hàng Redux. Chúng tôi có thể viết một bộ chọn isFormReady, tạo các hành động và một bộ giảm bớt. Nó sẽ hoạt động tốt, nhưng câu hỏi đặt ra là liệu đó có phải là nơi thích hợp cho những thông tin như vậy. Trong hầu hết các trường hợp, câu trả lời là "không".

Trạng thái ứng dụng

Trạng thái ứng dụng là trạng thái dẫn đến trải nghiệm tổng thể của người dùng. Đó có thể là trạng thái ủy quyền, dữ liệu hồ sơ hoặc chủ đề toàn cầu. Trạng thái như vậy có thể cần thiết ở mọi nơi trong ứng dụng. Đó là lý do tại sao biểu mẫu từ phần trước không thuộc loại này. Đầu vào của người dùng thường được xác định trong phạm vi chức năng cụ thể. Trạng thái mà chúng ta cần ở đó sẽ chết ngay sau khi tương tác kết thúc. Trạng thái ứng dụng là một phần dữ liệu khác cần tồn tại trong toàn bộ hành trình của người dùng. Đây là một ví dụ nhanh:

const ThemeContext = React.createContext();
const Theme = () => {
  const { theme } = useContext(ThemeContext);
  return <div style={{
    background: theme === 'light' ? 'white' : 'grey'
  }}>Hello world</div>;
}
const ThemeSelector = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);
  return (
    <select value={theme} onChange={toggleTheme}>
      <option value="light">light</option>
      <option value="dark">dark</option>
    </select>
  );
}

function App() {
  const [theme, setTheme] = useState('light');
  const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <header>
        <Theme />
      </header>
      <footer>
        <ThemeSelector />
      </footer>
    </ThemeContext.Provider>
  );
}                                                      

Ở đây chúng ta có một đầu trang và một chân trang. Cả hai đều cần biết chủ đề hiện tại của ứng dụng. Ví dụ đơn giản nhưng hãy tưởng tượng rằng ThemeThemeSelectorlà các thành phần được lồng sâu vào các thành phần khác. Họ không có quyền truy cập trực tiếp vào themebiến. Họ cũng sử dụng nó cho những việc khác nhau. Themechỉ hiển thị giá trị hiện tại trong khi ThemeSelectorthay đổi nó.

Chúng ta có thể nhận ra trạng thái như vậy nhanh hơn trạng thái tính năng. Nếu một thứ gì đó được sử dụng rộng rãi và cần cập nhật từ các thành phần ở xa, thì có lẽ chúng ta phải đưa nó vào trạng thái ứng dụng. Đây cũng là hành động hấp dẫn nhất đối với hầu hết các nhà phát triển. Trước tiên, chúng tôi xem xét việc sử dụng tính năng hoặc thậm chí trạng thái cục bộ. Nó sẽ làm cho cuộc sống của chúng tôi dễ dàng hơn.

Trạng thái máy chủ

Cuối cùng, có một loại trạng thái khác không tồn tại trong trình duyệt. Đó là khi chúng ta sử dụng một số lưu trữ liên tục. Giống như một cơ sở dữ liệu. Vài năm trở lại đây, chúng ta đang thấy ngày càng nhiều công cụ theo hướng đó. Ví dụ, GraphQL đôi khi được sử dụng làm bộ nhớ cho một trạng thái ứng dụng. Tất cả dữ liệu nằm bên ngoài ứng dụng và các công cụ như Apollo xử lý việc tìm nạp và đồng bộ hóa dữ liệu. ReactQuery là một ví dụ khác về điều đó.

Về mặt triển khai, việc quản lý nhà nước được tóm tắt thành một hook hoặc một thành phần. Chúng tôi sử dụng nó và không nghĩ nhiều về vòng đời của dữ liệu. Đây là một ví dụ sử dụng ReactQuery:

import { QueryClient, QueryClientProvider, useMutation, useQuery } from 'react-query'

const queryClient = new QueryClient()

function Example() {
  const { isLoading, error, data } = useQuery('my-data', loadData, { initialData: '' });
  const { mutate } = useMutation(saveData, {
    onSuccess: () => {
       queryClient.invalidateQueries('my-data')
     },
   });

  return (
    <div>
      <p>{data}</p>
      <input type="text" onChange={e => mutate(e.target.value) } defaultValue={data}/>
    </div>
  )
}
function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

ReactDOM.render(<App />, document.querySelector('#root'));

async function saveData(value) {
  return new Promise(done => {
    setTimeout(() => {
      localStorage.setItem('my-data', value);
      done();
    }, 1000);
  })
}
async function loadData() {
  return new Promise(done => {
    setTimeout(() => { done(localStorage.getItem('my-data')); }, 1000);
  });
}

saveDataloadDataở đây để mô phỏng một cơ sở dữ liệu. Chúng tôi đang bao bọc localStorageAPI trong các lời hứa đồng bộ, để làm cho nó trông giống như mất một thời gian. Chúng tôi sẽ giả vờ rằng chúng tôi truy vấn một cơ sở dữ liệu từ xa. Thành <Example>phần sử dụng useQueryuseMutationđể tải và lưu dữ liệu. Có một kỹ thuật để triển khai các cập nhật lạc quan sẽ làm cho bản trình diễn của chúng tôi trở nên linh hoạt. Nó sẽ giống như chúng ta đã làm với `useState.

Tất nhiên, với ví dụ này, chúng tôi chỉ đang làm xước bề mặt. Các thư viện như ReactQuery có thể làm được nhiều hơn thế. Bộ nhớ đệm dữ liệu, vô hiệu hóa dữ liệu, xử lý lỗi, logic dự phòng, v.v. Tất cả những việc mà chúng ta thường tự làm.

Kết luận

Việc tối ưu hóa quản lý nhà nước bắt đầu từ việc xác định chúng ta có loại trạng thái nào. Nó tiếp tục với việc chọn công cụ phù hợp cho công việc. Ngày nay, React như một thư viện cung cấp nhiều công cụ để quản lý trạng thái. Các móc và API ngữ cảnh đủ tốt cho hầu hết các trường hợp. Nếu chúng không phù hợp thì chúng tôi có nhiều công cụ của bên thứ ba tùy ý sử dụng. Ví dụ, Reduxbộ công cụ Redux vẫn còn tồn tại. Các thư viện như ReactQuery đang cố gắng tìm vị trí của họ trong hệ sinh thái. Chúng tôi có rất nhiều tùy chọn khác nhau về công cụ. Điều cuối cùng chúng ta nên nhớ là quản lý nhà nước thiên về việc tìm ra loại hình của nhà nước. Đó là ít hơn về các công cụ chúng tôi sử dụng.

Nguồn: https://calendar.perfplanet.com

#react 

What is GEEK

Buddha Community

Tối ưu hóa quản lý trạng thái trong các ứng dụng React
Autumn  Blick

Autumn Blick

1598839687

How native is React Native? | React Native vs Native App Development

If you are undertaking a mobile app development for your start-up or enterprise, you are likely wondering whether to use React Native. As a popular development framework, React Native helps you to develop near-native mobile apps. However, you are probably also wondering how close you can get to a native app by using React Native. How native is React Native?

In the article, we discuss the similarities between native mobile development and development using React Native. We also touch upon where they differ and how to bridge the gaps. Read on.

A brief introduction to React Native

Let’s briefly set the context first. We will briefly touch upon what React Native is and how it differs from earlier hybrid frameworks.

React Native is a popular JavaScript framework that Facebook has created. You can use this open-source framework to code natively rendering Android and iOS mobile apps. You can use it to develop web apps too.

Facebook has developed React Native based on React, its JavaScript library. The first release of React Native came in March 2015. At the time of writing this article, the latest stable release of React Native is 0.62.0, and it was released in March 2020.

Although relatively new, React Native has acquired a high degree of popularity. The “Stack Overflow Developer Survey 2019” report identifies it as the 8th most loved framework. Facebook, Walmart, and Bloomberg are some of the top companies that use React Native.

The popularity of React Native comes from its advantages. Some of its advantages are as follows:

  • Performance: It delivers optimal performance.
  • Cross-platform development: You can develop both Android and iOS apps with it. The reuse of code expedites development and reduces costs.
  • UI design: React Native enables you to design simple and responsive UI for your mobile app.
  • 3rd party plugins: This framework supports 3rd party plugins.
  • Developer community: A vibrant community of developers support React Native.

Why React Native is fundamentally different from earlier hybrid frameworks

Are you wondering whether React Native is just another of those hybrid frameworks like Ionic or Cordova? It’s not! React Native is fundamentally different from these earlier hybrid frameworks.

React Native is very close to native. Consider the following aspects as described on the React Native website:

  • Access to many native platforms features: The primitives of React Native render to native platform UI. This means that your React Native app will use many native platform APIs as native apps would do.
  • Near-native user experience: React Native provides several native components, and these are platform agnostic.
  • The ease of accessing native APIs: React Native uses a declarative UI paradigm. This enables React Native to interact easily with native platform APIs since React Native wraps existing native code.

Due to these factors, React Native offers many more advantages compared to those earlier hybrid frameworks. We now review them.

#android app #frontend #ios app #mobile app development #benefits of react native #is react native good for mobile app development #native vs #pros and cons of react native #react mobile development #react native development #react native experience #react native framework #react native ios vs android #react native pros and cons #react native vs android #react native vs native #react native vs native performance #react vs native #why react native #why use react native

Hoang  Ha

Hoang Ha

1639380504

Tối ưu hóa quản lý trạng thái trong các ứng dụng React

Xây dựng giao diện người dùng luôn là một thách thức. Một trong những vấn đề cần giải quyết chính là quản lý nhà nước. Ứng dụng React không phải là một ngoại lệ. Khi Facebook công bố thư viện, chúng tôi đã coi nó là một lớp xem . Nhanh chóng sau đó, chúng tôi nhận ra rằng nó còn hơn thế nữa. Với luồng dữ liệu một hướng, React đã làm cho việc phát triển front-end trở nên dễ đoán và mạnh mẽ hơn một chút. Tuy nhiên, câu trả lời cho một câu hỏi quan trọng đã bị thiếu - “Chúng ta quản lý nhà nước như thế nào?”. Trong những năm qua, Facebook và cộng đồng React đã có nhiều loại giải pháp khác nhau. Trong bài viết này, chúng ta sẽ xem một số trong số chúng và sẽ đưa ra lời khuyên về thời điểm sử dụng chúng.

Bước đầu tiên để giải quyết vấn đề là xác định vấn đề

Quản lý nhà nước đã khó và càng khó hơn nếu chúng ta làm không đúng chỗ. Bước đầu tiên là xác định loại trạng thái mà chúng ta đang đối phó. Có nhiều loại khác nhau, và việc ủi loại nào chúng ta có là rất quan trọng đối với công cụ sau đó. Nếu chúng tôi đánh giá sai vào thời điểm này, chúng tôi sẽ kết thúc với một thiết lập không tối ưu. Vì vậy, trả lời câu hỏi "Cái gì sống ở đâu?" câu hỏi là quan trọng.

Tiểu bang địa phương

Một trạng thái chỉ tồn tại trong một thành phần duy nhất mà chúng tôi coi là cục bộ. Một ví dụ về điều đó là chức năng xem thêm. Hãy tưởng tượng chúng ta có một văn bản dài, nhưng chúng ta cắt bớt nó và hiển thị một liên kết nhỏ ở cuối. Nếu người dùng nhấp vào nó, chúng tôi sẽ tiết lộ nội dung. Chúng tôi cần một lá cờ cho chúng tôi biết liệu liên kết có được nhấn hay không.

function Text() {
  const [viewMore, setViewMore] = useState(false);

  return (
    <Fragment>
      <p>
        React makes it painless to create interactive UIs. 
        {
          viewMore && <span>
            Design simple views for each state in your application.
          </span>
        }
      </p>
      <button onClick={() => setViewMore(true)}>read more</button>
    </Fragment>
  );
}                                                                          

Việc sử dụng useStatetrong thành phần này là quản lý nhà nước của chúng tôi. Một kỹ thuật để xác định loại trạng thái này là hỏi ai cần biết về nó. Trong trường hợp này, nó chỉ là <Text>thành phần của chúng ta . Vì vậy, thật hợp lý khi tạo viewMorecờ ngay tại nơi chúng ta sẽ tiêu thụ giá trị.

Các vấn đề với nhà nước địa phương xảy ra rất thường xuyên khi chúng ta cố gắng quản lý quá nhiều thứ. Chúng tôi định vị trạng thái một cách chính xác, nhưng logic yêu cầu nhiều biến. Hãy xem xét ví dụ sau:

function ILoveCats() {
  const [cat, setCatURL] = useState(null);
  const [isLoading, setLoadingFlag] = useState(false);
  const [error, setError] = useState(null);

  async function getCat() {
    setLoadingFlag(true);
    try {
      const query = await fetch('https://api.thecatapi.com/v1/images/search');
      const [{ url }] = await query.json();
      setLoadingFlag(false);
      setCatURL(url);
    } catch(error) {
      setError(true)
    }
  }
  return (
    <>
      <button onClick={getCat}>I love cats</button>
      { error && 'Meow! Meow!'}
      { isLoading && 'Loading ...'}
      { cat && <img src={cat} /> }
    </>
  )
}                                         

Thành <ILoveCats>phần này cung cấp một tính năng hiển thị hình ảnh của một con mèo trên màn hình. Người dùng cần nhấn một nút và getCatchức năng này sẽ cung cấp URL của hình ảnh. Lưu ý cách chúng ta có ba biến để quản lý toàn bộ quá trình. Chúng tôi có một cái giữ URL, một cái khác cho chúng tôi biết yêu cầu có đang được thực hiện hay không và một cái thông báo lỗi. Chúng tôi có thể nghĩ đến một số trường hợp cạnh tranh khác, và chúng tôi có thể sẽ mang đến nhiều useStatephát biểu hơn . Trong trường hợp này, một trong những giải pháp khả thi là xem xét một cỗ máy trạng thái.

const STATES = {
  IDLE: 'IDLE',
  LOADING: 'LOADING',
  SUCCESS: 'SUCCESS',
  ERROR: 'ERROR'
}
function ILoveCats() {
  const [status, setStatus] = useState({ value: STATES.IDLE });

  async function getCat() {
    setStatus({ value: STATES.LOADING });
    try {
      const query = await fetch('https://api.thecatapi.com/v1/images/search');
      const [{ url }] = await query.json();
      setStatus({ value: STATES.SUCCESS, url });
    } catch(error) {
      setStatus({ value: STATES.ERROR });
    }
  }
  return (
    <>
      <button onClick={getCat}>I love cats</button>
      { status.value === STATES.ERROR && 'Meow! Meow!'}
      { status.value === STATES.LOADING  && 'Loading ...'}
      { status.value === STATES.SUCCESS  && <img src={status.url} /> }
    </>
  )
}   

Với phiên bản thành phần mới này, chúng tôi chỉ có một biến - status. Nó giữ tiến độ hiện tại của người dùng. Chúng ta có thể nói rất nhiều về máy trạng thái và lợi ích của chúng. Nếu bạn muốn khám phá khái niệm này, hãy nhớ xem XState . Chúng tôi phải làm rõ rằng chúng tôi đã không triển khai một máy trạng thái hoàn chỉnh. Chúng tôi không có định nghĩa chuyển đổi. Nhưng ngay cả khi không có điều đó, thành phần đọc tốt hơn và nó trở nên dễ dàng hơn để tuân theo logic.

Loại trạng thái tiếp theo mà chúng ta sẽ nói đến là kết hợp nhiều thành phần.

Trạng thái tính năng

Trạng thái tính năng là khi chúng ta có hai hoặc nhiều thành phần chia sẻ cùng một thông tin. Ví dụ về trạng thái như vậy là mọi biểu mẫu chứa nhiều đầu vào. Hãy minh họa bằng một ví dụ:

const Skill = ({ onChange }) => (
  <label> Skill:
    <input type="text" onChange={e => onChange(e.target.value)}/>
  </label>
);
const Years = ({ onChange }) => (
  <label> Years of experience:
    <input type="text" onChange={e => onChange(e.target.value)}/>
  </label>
);

function Form() {
  const [skill, setSkill] = useState('');
  const [years, setYears] = useState('');

  const isFormReady = skill !== '' && years !== '';

  return (
    <form>
      <Skill onChange={setSkill} />
      <Years onChange={setYears} />
      <button disabled={!isFormReady}>submit</button>
    </form>
  );
}                                 

Một biểu mẫu có hai đầu vào văn bản. Người dùng nhập giá trị vào cả hai trường. Chúng tôi tắt nút theo mặc định và chỉ bật nó khi chúng tôi có hai giá trị. Để ý xem chúng ta cần skillsyearsđóng từng cái như thế nào để có thể tính toán isFormReady. Thành <Form>phần là một nơi hoàn hảo để thực hiện logic như vậy vì nó bao bọc tất cả các đầu vào. Thường thì các thành phần như vậy quản lý một đối tượng dữ liệu có chứa tất cả thông tin biểu mẫu. Ví dụ này cho thấy ranh giới mỏng giữa tính năng và trạng thái ứng dụng (chúng ta sẽ thấy nó trong phần tiếp theo). Chúng tôi có thể dễ dàng đưa trạng thái đó vào cửa hàng Redux. Chúng tôi có thể viết một bộ chọn isFormReady, tạo các hành động và một bộ giảm bớt. Nó sẽ hoạt động tốt, nhưng câu hỏi đặt ra là liệu đó có phải là nơi thích hợp cho những thông tin như vậy. Trong hầu hết các trường hợp, câu trả lời là "không".

Trạng thái ứng dụng

Trạng thái ứng dụng là trạng thái dẫn đến trải nghiệm tổng thể của người dùng. Đó có thể là trạng thái ủy quyền, dữ liệu hồ sơ hoặc chủ đề toàn cầu. Trạng thái như vậy có thể cần thiết ở mọi nơi trong ứng dụng. Đó là lý do tại sao biểu mẫu từ phần trước không thuộc loại này. Đầu vào của người dùng thường được xác định trong phạm vi chức năng cụ thể. Trạng thái mà chúng ta cần ở đó sẽ chết ngay sau khi tương tác kết thúc. Trạng thái ứng dụng là một phần dữ liệu khác cần tồn tại trong toàn bộ hành trình của người dùng. Đây là một ví dụ nhanh:

const ThemeContext = React.createContext();
const Theme = () => {
  const { theme } = useContext(ThemeContext);
  return <div style={{
    background: theme === 'light' ? 'white' : 'grey'
  }}>Hello world</div>;
}
const ThemeSelector = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);
  return (
    <select value={theme} onChange={toggleTheme}>
      <option value="light">light</option>
      <option value="dark">dark</option>
    </select>
  );
}

function App() {
  const [theme, setTheme] = useState('light');
  const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <header>
        <Theme />
      </header>
      <footer>
        <ThemeSelector />
      </footer>
    </ThemeContext.Provider>
  );
}                                                      

Ở đây chúng ta có một đầu trang và một chân trang. Cả hai đều cần biết chủ đề hiện tại của ứng dụng. Ví dụ đơn giản nhưng hãy tưởng tượng rằng ThemeThemeSelectorlà các thành phần được lồng sâu vào các thành phần khác. Họ không có quyền truy cập trực tiếp vào themebiến. Họ cũng sử dụng nó cho những việc khác nhau. Themechỉ hiển thị giá trị hiện tại trong khi ThemeSelectorthay đổi nó.

Chúng ta có thể nhận ra trạng thái như vậy nhanh hơn trạng thái tính năng. Nếu một thứ gì đó được sử dụng rộng rãi và cần cập nhật từ các thành phần ở xa, thì có lẽ chúng ta phải đưa nó vào trạng thái ứng dụng. Đây cũng là hành động hấp dẫn nhất đối với hầu hết các nhà phát triển. Trước tiên, chúng tôi xem xét việc sử dụng tính năng hoặc thậm chí trạng thái cục bộ. Nó sẽ làm cho cuộc sống của chúng tôi dễ dàng hơn.

Trạng thái máy chủ

Cuối cùng, có một loại trạng thái khác không tồn tại trong trình duyệt. Đó là khi chúng ta sử dụng một số lưu trữ liên tục. Giống như một cơ sở dữ liệu. Vài năm trở lại đây, chúng ta đang thấy ngày càng nhiều công cụ theo hướng đó. Ví dụ, GraphQL đôi khi được sử dụng làm bộ nhớ cho một trạng thái ứng dụng. Tất cả dữ liệu nằm bên ngoài ứng dụng và các công cụ như Apollo xử lý việc tìm nạp và đồng bộ hóa dữ liệu. ReactQuery là một ví dụ khác về điều đó.

Về mặt triển khai, việc quản lý nhà nước được tóm tắt thành một hook hoặc một thành phần. Chúng tôi sử dụng nó và không nghĩ nhiều về vòng đời của dữ liệu. Đây là một ví dụ sử dụng ReactQuery:

import { QueryClient, QueryClientProvider, useMutation, useQuery } from 'react-query'

const queryClient = new QueryClient()

function Example() {
  const { isLoading, error, data } = useQuery('my-data', loadData, { initialData: '' });
  const { mutate } = useMutation(saveData, {
    onSuccess: () => {
       queryClient.invalidateQueries('my-data')
     },
   });

  return (
    <div>
      <p>{data}</p>
      <input type="text" onChange={e => mutate(e.target.value) } defaultValue={data}/>
    </div>
  )
}
function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

ReactDOM.render(<App />, document.querySelector('#root'));

async function saveData(value) {
  return new Promise(done => {
    setTimeout(() => {
      localStorage.setItem('my-data', value);
      done();
    }, 1000);
  })
}
async function loadData() {
  return new Promise(done => {
    setTimeout(() => { done(localStorage.getItem('my-data')); }, 1000);
  });
}

saveDataloadDataở đây để mô phỏng một cơ sở dữ liệu. Chúng tôi đang bao bọc localStorageAPI trong các lời hứa đồng bộ, để làm cho nó trông giống như mất một thời gian. Chúng tôi sẽ giả vờ rằng chúng tôi truy vấn một cơ sở dữ liệu từ xa. Thành <Example>phần sử dụng useQueryuseMutationđể tải và lưu dữ liệu. Có một kỹ thuật để triển khai các cập nhật lạc quan sẽ làm cho bản trình diễn của chúng tôi trở nên linh hoạt. Nó sẽ giống như chúng ta đã làm với `useState.

Tất nhiên, với ví dụ này, chúng tôi chỉ đang làm xước bề mặt. Các thư viện như ReactQuery có thể làm được nhiều hơn thế. Bộ nhớ đệm dữ liệu, vô hiệu hóa dữ liệu, xử lý lỗi, logic dự phòng, v.v. Tất cả những việc mà chúng ta thường tự làm.

Kết luận

Việc tối ưu hóa quản lý nhà nước bắt đầu từ việc xác định chúng ta có loại trạng thái nào. Nó tiếp tục với việc chọn công cụ phù hợp cho công việc. Ngày nay, React như một thư viện cung cấp nhiều công cụ để quản lý trạng thái. Các móc và API ngữ cảnh đủ tốt cho hầu hết các trường hợp. Nếu chúng không phù hợp thì chúng tôi có nhiều công cụ của bên thứ ba tùy ý sử dụng. Ví dụ, Reduxbộ công cụ Redux vẫn còn tồn tại. Các thư viện như ReactQuery đang cố gắng tìm vị trí của họ trong hệ sinh thái. Chúng tôi có rất nhiều tùy chọn khác nhau về công cụ. Điều cuối cùng chúng ta nên nhớ là quản lý nhà nước thiên về việc tìm ra loại hình của nhà nước. Đó là ít hơn về các công cụ chúng tôi sử dụng.

Nguồn: https://calendar.perfplanet.com

#react 

Hoang  Ha

Hoang Ha

1660764600

Một Cách Thực Tế để Quản Lý Trạng Thái Trang Trong ứng Dụng React

Có rất nhiều thư viện quản lý trạng thái trong React, chẳng hạn như Redux, Rematch, Recoil và tất nhiên, bạn có thể sử dụng React context để quản lý trạng thái của trang. Tất cả đều rất hữu ích, nhưng có một vấn đề - khi chúng tôi làm mới trang, trạng thái trang sẽ bị mất và trạng thái trang sẽ không thể chia sẻ được. Ví dụ: nếu bạn lọc một số dữ liệu trong trang danh sách ứng dụng React và muốn chia sẻ URL trang với ai đó có thể trực tiếp xem kết quả, bạn không thể triển khai nó chỉ với sự quản lý của nhà nước.

Bài viết này sẽ giới thiệu việc sử dụng API Lịch sử để nâng cao trạng thái React để trạng thái có thể được chia sẻ và hiển thị trang sẽ không thay đổi sau khi làm mới trang.

Trạng thái liên tục với URL

Hầu hết các mô-đun npm sử dụng localStorage để duy trì trạng thái trang trong các ứng dụng React như redux-Pers - npm (npmjs.com) , use-persisted-state - npm (npmjs.com) . Bằng cách sử dụng localStorage, chúng tôi có thể lưu trữ dữ liệu phức tạp hoặc dữ liệu lớn và khi làm mới trang, chúng tôi có thể khôi phục trạng thái, đó là trải nghiệm tốt hơn cho người dùng, đặc biệt là trên trang di động.

Đối với hầu hết các trang danh sách, chúng tôi chỉ cần duy trì một số trạng thái của hành động lọc, chúng tôi có thể sử dụng một URL để lưu trữ trạng thái. Giả sử chúng ta chỉ cần lưu trữ một trường, chúng ta có thể sử dụng React hook này:

const useHistory = () => {
  const { pathname, search } = window.location;
  const queryParams = new URLSearchParams(search);
  const [filter, setFilter] = React.useState(queryParams.get("filter") || "");
  return [
    text,
    function setData(val) {
      setFilter(val);
      queryParams.set("filter", val);
      history.replaceState({}, "", `${pathname}?${queryParams.toString()}`);
    }
  ];
};

Khi sử dụng hàm hook, nó sẽ nhận được truy vấn URL filterđể khởi tạo biến bộ lọc và chúng ta có thể sử dụng setData để lưu trữ trạng thái và nó sẽ lưu trữ trạng thái thành URL.

Có một bản demo ứng dụng React:

https://codepen.io/bitbug/pen/ZExqgxK

Bằng cách sử dụng URL để duy trì trạng thái và chúng tôi có thể chia sẻ liên kết (CodePen không chia sẻ vì nó sử dụng iframe để hiển thị trang kết quả).

Sự kết luận

Chúng ta có thể sử dụng localStorage để duy trì trạng thái, nhưng cũng có thể sử dụng URL để làm điều đó. Nếu chúng ta cần chia sẻ URL trang với một số bộ lọc / tùy chọn đặt trước, thì việc sử dụng URL để lưu trữ trạng thái sẽ rất tiện lợi. Nếu dữ liệu trạng thái rất lớn, chúng tôi có thể lưu nó vào SQL phụ trợ với một id ngắn có thể được chia sẻ với những người khác.

Nguồn: https://javascript.plainenglish.io/a-practical-way-to-manage-page-state-in-a-react-app-c542828076ab

#react 

Mathew Rini

1615544450

How to Select and Hire the Best React JS and React Native Developers?

Since March 2020 reached 556 million monthly downloads have increased, It shows that React JS has been steadily growing. React.js also provides a desirable amount of pliancy and efficiency for developing innovative solutions with interactive user interfaces. It’s no surprise that an increasing number of businesses are adopting this technology. How do you select and recruit React.js developers who will propel your project forward? How much does a React developer make? We’ll bring you here all the details you need.

What is React.js?

Facebook built and maintains React.js, an open-source JavaScript library for designing development tools. React.js is used to create single-page applications (SPAs) that can be used in conjunction with React Native to develop native cross-platform apps.

React vs React Native

  • React Native is a platform that uses a collection of mobile-specific components provided by the React kit, while React.js is a JavaScript-based library.
  • React.js and React Native have similar syntax and workflows, but their implementation is quite different.
  • React Native is designed to create native mobile apps that are distinct from those created in Objective-C or Java. React, on the other hand, can be used to develop web apps, hybrid and mobile & desktop applications.
  • React Native, in essence, takes the same conceptual UI cornerstones as standard iOS and Android apps and assembles them using React.js syntax to create a rich mobile experience.

What is the Average React Developer Salary?

In the United States, the average React developer salary is $94,205 a year, or $30-$48 per hour, This is one of the highest among JavaScript developers. The starting salary for junior React.js developers is $60,510 per year, rising to $112,480 for senior roles.

* React.js Developer Salary by Country

  • United States- $120,000
  • Canada - $110,000
  • United Kingdom - $71,820
  • The Netherlands $49,095
  • Spain - $35,423.00
  • France - $44,284
  • Ukraine - $28,990
  • India - $9,843
  • Sweden - $55,173
  • Singapore - $43,801

In context of software developer wage rates, the United States continues to lead. In high-tech cities like San Francisco and New York, average React developer salaries will hit $98K and $114per year, overall.

However, the need for React.js and React Native developer is outpacing local labour markets. As a result, many businesses have difficulty locating and recruiting them locally.

It’s no surprise that for US and European companies looking for professional and budget engineers, offshore regions like India are becoming especially interesting. This area has a large number of app development companies, a good rate with quality, and a good pool of React.js front-end developers.

As per Linkedin, the country’s IT industry employs over a million React specialists. Furthermore, for the same or less money than hiring a React.js programmer locally, you may recruit someone with much expertise and a broader technical stack.

How to Hire React.js Developers?

  • Conduct thorough candidate research, including portfolios and areas of expertise.
  • Before you sit down with your interviewing panel, do some homework.
  • Examine the final outcome and hire the ideal candidate.

Why is React.js Popular?

React is a very strong framework. React.js makes use of a powerful synchronization method known as Virtual DOM, which compares the current page architecture to the expected page architecture and updates the appropriate components as long as the user input.

React is scalable. it utilises a single language, For server-client side, and mobile platform.

React is steady.React.js is completely adaptable, which means it seldom, if ever, updates the user interface. This enables legacy projects to be updated to the most new edition of React.js without having to change the codebase or make a few small changes.

React is adaptable. It can be conveniently paired with various state administrators (e.g., Redux, Flux, Alt or Reflux) and can be used to implement a number of architectural patterns.

Is there a market for React.js programmers?
The need for React.js developers is rising at an unparalleled rate. React.js is currently used by over one million websites around the world. React is used by Fortune 400+ businesses and popular companies such as Facebook, Twitter, Glassdoor and Cloudflare.

Final thoughts:

As you’ve seen, locating and Hire React js Developer and Hire React Native developer is a difficult challenge. You will have less challenges selecting the correct fit for your projects if you identify growing offshore locations (e.g. India) and take into consideration the details above.

If you want to make this process easier, You can visit our website for more, or else to write a email, we’ll help you to finding top rated React.js and React Native developers easier and with strives to create this operation

#hire-react-js-developer #hire-react-native-developer #react #react-native #react-js #hire-react-js-programmer

Duong Tran

Duong Tran

1648032360

Cách Quản Lý Trạng Thái Trong Ứng Dụng React - Với Hooks, Redux, V.v

Chào! Trong bài viết này, chúng ta sẽ xem xét nhiều cách bạn có thể quản lý trạng thái trong ứng dụng React.

Chúng ta sẽ bắt đầu bằng cách nói về trạng thái là gì, sau đó đi qua nhiều công cụ bạn có thể sử dụng để quản lý nó.

Chúng ta sẽ xem xét hook useState đơn giản và cũng tìm hiểu về các thư viện phức tạp hơn như Redux. Sau đó, chúng tôi sẽ kiểm tra các tùy chọn gần đây nhất có sẵn như Recoil và Zustand.

Trạng thái trong React là gì?

Trong React hiện đại, chúng tôi xây dựng các ứng dụng của mình với các thành phần chức năng . Bản thân các thành phần là các hàm JavaScript, các bit mã độc lập và có thể tái sử dụng .

Mục đích của việc xây dựng ứng dụng với các thành phần là có kiến ​​trúc mô-đun, với sự phân tách rõ ràng các mối quan tâm. Điều này làm cho mã dễ hiểu hơn, dễ bảo trì hơn và dễ sử dụng lại khi có thể.

Trạng thái là một đối tượng chứa thông tin về một thành phần nào đó. Các hàm JavaScript thuần túy không có khả năng lưu trữ thông tin. Mã bên trong chúng thực thi và "biến mất" sau khi quá trình thực thi kết thúc.

Nhưng nhờ trạng thái, các thành phần chức năng của React có thể lưu trữ thông tin ngay cả sau khi thực thi. Khi chúng ta cần một thành phần để lưu trữ hoặc "ghi nhớ" một cái gì đó, hoặc hoạt động theo một cách khác tùy thuộc vào môi trường, trạng thái là những gì chúng ta cần để làm cho nó hoạt động theo cách này.

Điều quan trọng cần đề cập là không phải tất cả các thành phần trong ứng dụng React đều phải có trạng thái. Có những thành phần không trạng thái cũng chỉ hiển thị nội dung của nó mà không cần lưu trữ bất kỳ thông tin nào, và điều đó thật ổn.

Một điều quan trọng khác cần đề cập là thay đổi trạng thái là một trong hai điều khiến một thành phần React được kết xuất lại (thứ còn lại là sự thay đổi về đạo cụ). Bằng cách này, trạng thái lưu trữ thông tin về thành phần và cũng kiểm soát hành vi của nó.

Cách sử dụng UseState Hook

Để triển khai trạng thái trong các thành phần của chúng ta, React cung cấp cho chúng ta một hook gọi là useState . Hãy xem nó hoạt động như thế nào với ví dụ sau.

Chúng tôi sẽ sử dụng ví dụ về bộ đếm cổ điển, trong đó chúng tôi đang hiển thị một số và chúng tôi có một số nút để tăng, giảm hoặc đặt lại số đó.

Đây là một ví dụ điển hình về một ứng dụng mà chúng ta cần lưu trữ một phần thông tin và hiển thị một cái gì đó khác nhau mỗi khi thông tin đó thay đổi.

5bueYQblr - 2-

Mã cho ứng dụng này trông giống như sau:

// App.js
import { useState } from 'react'

function App() {

  const [count, setCount] = useState(0)

  return (
    <div className="App">
      <p>Count is: {count}</p>

      <div>
        <button onClick={() => setCount(count+1)}>Add 1</button>
        <button onClick={() => setCount(count-1)}>Decrease 1</button>

        <button onClick={() => setCount(count+10)}>Add 10</button>
        <button onClick={() => setCount(count-10)}>Decrease 10</button>

        <button onClick={() => setCount(0)}>Reset count</button>
      </div>
    </div>
  )
}

export default App

Đầu tiên, chúng tôi nhập hook từ React:import { useState } from 'react'

Sau đó, chúng tôi khởi tạo trạng thái: const [count, setCount] = useState(0)

Ở đây chúng tôi cung cấp một tên biến cho trạng thái ( count) và một tên hàm mà chúng tôi sẽ sử dụng mỗi khi chúng tôi cần cập nhật trạng thái đó ( setCount). Cuối cùng, chúng tôi đặt giá trị ban đầu của trạng thái ( 0), giá trị này sẽ là giá trị được tải theo mặc định mỗi khi ứng dụng khởi động.

  • Cuối cùng, như đã nói ở trên, mỗi khi muốn cập nhật trạng thái, chúng ta phải sử dụng hàm mà chúng ta đã khai báo: setCountĐể sử dụng nó, chúng ta chỉ cần gọi nó truyền trạng thái mới mà chúng ta muốn làm tham số. Tức là, nếu chúng ta muốn thêm 1 vào bất động sản trước đó, chúng ta sẽ gọi setCount(count+1).

Như đã đề cập, điều này sẽ gây ra cập nhật trạng thái và do đó kết xuất lại thành phần. Điều này trong ứng dụng của chúng tôi có nghĩa là chúng tôi sẽ thấy trên màn hình rằng quầy sẽ đi lên.

Cách sử dụng useTác động để đọc cập nhật trạng thái

Điều quan trọng cần đề cập là hàm setState là không đồng bộ . Vì vậy, nếu chúng tôi cố gắng đọc trạng thái ngay lập tức sau khi cập nhật nó, như thế này:

<button onClick={() => {
          setCount(count+1)
          console.log(count)
}}>Add 1</button>

chúng tôi sẽ nhận được giá trị trước đó của trạng thái mà không cần cập nhật.

Cách chính xác để đọc trạng thái sau khi cập nhật sẽ sử dụng hook useEffect . Nó cho phép chúng tôi thực thi một hàm sau mỗi thành phần hiển thị lại (theo mặc định) hoặc sau bất kỳ biến cụ thể nào mà chúng tôi khai báo các thay đổi.

Một cái gì đó như thế này:

useEffect(() => console.log(value), [value])

Cách chuyển một lệnh gọi lại đến chức năng cập nhật trạng thái

Ngoài ra, thực tế là useState là không đồng bộ có ý nghĩa khi xem xét các thay đổi trạng thái rất thường xuyên và nhanh chóng.

Ví dụ: lấy trường hợp người dùng nhấn nút THÊM nhiều lần liên tiếp hoặc một vòng lặp phát ra sự kiện nhấp chuột một số lần nhất định.

Bằng cách cập nhật trạng thái setCount(count+1), chúng tôi chấp nhận rủi ro rằng nó countsẽ không được cập nhật khi sự kiện tiếp theo được kích hoạt.

Ví dụ, hãy nói ở phần đầu count = 0. Sau đó setCount(count+1)được gọi và trạng thái được cập nhật không đồng bộ.
Nhưng sau đó một lần nữa setCount(count+1)được gọi, trước khi cập nhật trạng thái được hoàn thành. Điều này có nghĩa là vẫn còn count = 0, có nghĩa là thứ hai setCountsẽ không cập nhật trạng thái một cách chính xác.

Một cách tiếp cận phòng thủ hơn sẽ là chuyển setCountmột lệnh gọi lại, như sau:setCount(prevCount => prevCount+1)

Điều này đảm bảo rằng giá trị cần cập nhật là giá trị mới nhất và giúp chúng tôi tránh xa sự cố được đề cập ở trên. Mỗi khi chúng tôi cập nhật trạng thái trước đó, chúng tôi nên sử dụng phương pháp này.

Quản lý quy mô và độ phức tạp

Cho đến nay, quản lý nhà nước dường như là một miếng bánh. Chúng tôi chỉ cần một hook, một giá trị và một hàm để cập nhật nó và chúng tôi đã sẵn sàng.

Nhưng một khi các ứng dụng bắt đầu trở nên lớn hơn và phức tạp hơn, việc chỉ sử dụng điều này có thể bắt đầu gây ra một số vấn đề.

Phản ứng ngữ cảnh

Vấn đề đầu tiên có thể xảy ra là khi chúng ta có nhiều thành phần lồng nhau, và chúng ta cần nhiều thành phần "anh chị em" để chia sẻ cùng một trạng thái.

Câu trả lời rõ ràng ở đây là "nâng" trạng thái lên, nghĩa là một thành phần cha sẽ là thành phần giữ trạng thái và nó sẽ chuyển nó làm đạo cụ cho các thành phần con.

Điều này hoạt động tốt, nhưng khi chúng ta có nhiều thành phần lồng vào nhau, chúng ta có thể cần chuyển các đạo cụ qua nhiều cấp độ thành phần. Điều này được gọi là "khoan chống đỡ" và không chỉ trông xấu xí mà còn tạo ra mã khó bảo trì.

Việc khoan lỗ cũng có thể gây ra các kết xuất không cần thiết , điều này có thể ảnh hưởng đến hiệu suất của ứng dụng của chúng tôi. Nếu giữa thành phần mẹ của chúng ta (thành phần lưu trữ trạng thái) và các thành phần con của chúng ta (chứa trạng thái) có các thành phần khác ("thành phần giữa"), chúng ta cũng sẽ cần chuyển các đạo cụ qua các thành phần giữa này, ngay cả khi chúng không cần chỗ dựa.

Điều này có nghĩa là các "thành phần giữa" này sẽ hiển thị lại khi prop thay đổi, ngay cả khi chúng không có gì khác để kết xuất.

Giải pháp cho vấn đề này là sử dụng React context , nói ngắn gọn là một cách để tạo một thành phần wrapper bao bọc xung quanh bất kỳ nhóm thành phần nào chúng ta muốn và có thể truyền đạo cụ trực tiếp đến các thành phần đó mà không cần phải "khoan" qua các thành phần không nhất thiết phải sử dụng trạng thái đó.

Điều cần chú ý khi sử dụng ngữ cảnh là khi trạng thái ngữ cảnh thay đổi, tất cả các thành phần được bao bọc nhận trạng thái đó sẽ hiển thị lại. Và điều này có thể không cần thiết tùy theo từng trường hợp và cũng có thể gây ra các vấn đề về hiệu suất.

Vì vậy, điều quan trọng là phải cân bằng xem chúng ta có thực sự cần tạo một trạng thái khả dụng cho nhiều thành phần hay không hay liệu chúng ta có thể giữ nó cục bộ trong một thành phần duy nhất hay không. Và nếu chúng ta cần cung cấp nó cho nhiều thành phần, thì việc đặt nó vào ngữ cảnh có thực sự là một ý kiến ​​hay hay chúng ta có thể nâng nó lên một cấp độ.

Kent C Dodds có một bài viết thú vị về chủ đề này.

Cách sử dụng UseReducer Hook

Một vấn đề khác có thể xảy ra khi bạn đang sử dụng useState trong đó trạng thái mới sẽ được đặt phụ thuộc vào trạng thái trước đó (như ví dụ về số lượng của chúng tôi) hoặc khi các thay đổi trạng thái xảy ra rất thường xuyên trong ứng dụng của chúng tôi.

Trong những trường hợp này, useState có thể gây ra một số hành vi bất ngờ và không thể đoán trước. Ra đời các bộ giảm tốc để giải quyết vấn đề này.

Bộ giảm thiểu là một hàm thuần túy lấy trạng thái trước đó và một hành động làm đối số và trả về trạng thái tiếp theo. Array.prototype.reduce(reducer, initialValue)Nó được gọi là bộ giảm vì nó cùng kiểu hàm mà bạn có thể truyền vào một mảng:.

useReducer là hook mà Reacts cung cấp cho phép chúng ta triển khai các bộ giảm bớt để quản lý trạng thái của chúng ta. Sử dụng hook này, ứng dụng ví dụ trước đây của chúng tôi sẽ trông như thế này:

// App.js
import { useReducer } from 'react'
import './App.scss'

function App() {

  function reducer(state, action) {
    switch (action.type) {
      case 'ADD': return { count: state.count + 1 }
      case 'SUB': return { count: state.count - 1 }
      case 'ADD10': return { count: state.count + 10 }
      case 'SUB10': return { count: state.count - 10 }
      case 'RESET': return { count: 0 }
      default: return state
    }
  }

  const [state, dispatch] = useReducer(reducer, { count: 0 })  

  return (
    <div className="App">
      <p>Count is: {state.count}</p>

      <div>
        <button onClick={() => dispatch({type: 'ADD'})}>Add 1</button>
        
        <button onClick={() => dispatch({type: 'SUB'})}>Decrease 1</button>

        <button onClick={() => dispatch({type: 'ADD10'})}>Add 10</button>
        <button onClick={() => dispatch({type: 'SUB10'})}>Decrease 10</button>

        <button onClick={() => dispatch({type: 'RESET'})}>Reset count</button>
      </div>
    </div>
  )
}

export default App

Một lần nữa, chúng ta bắt đầu bằng cách nhập hook từ React:import { useReducer } from 'react'

Sau đó, chúng tôi sẽ khai báo một hàm giảm thiểu, vì các tham số sẽ nhận trạng thái hiện tại và một hành động để thực hiện trên nó. Bên trong nó, nó sẽ có một câu lệnh switch sẽ đọc kiểu hành động, thực hiện hành động tương ứng trên trạng thái và trả về trạng thái đã cập nhật.

Thực tế phổ biến là sử dụng các câu lệnh switch trên các dấu giảm bớt và các chữ cái viết hoa để khai báo các hành động. ;)

function reducer(state, action) {
    switch (action.type) {
      case 'ADD': return { count: state.count + 1 }
      case 'SUB': return { count: state.count - 1 }
      case 'ADD10': return { count: state.count + 10 }
      case 'SUB10': return { count: state.count - 10 }
      case 'RESET': return { count: 0 }
      default: return state
    }
  }
  • Sau đó, đã đến lúc khai báo hook useReducer của chúng ta , trông khá giống với hook useState. Chúng tôi khai báo một giá trị cho trạng thái của chúng tôi ('trạng thái' trong trường hợp của chúng tôi), một hàm mà chúng tôi sẽ sử dụng để sửa đổi nó ('điều phối'), và sau đó useReducer sẽ lấy hàm giảm thiểu làm tham số đầu tiên và trạng thái mặc định làm tham số thứ hai.
const [state, dispatch] = useReducer(reducer, { count: 0 })  
  • Cuối cùng, để cập nhật trạng thái của chúng tôi, chúng tôi sẽ không gọi trực tiếp trình giảm bớt, mà thay vào đó chúng tôi sẽ gọi hàm mà chúng tôi vừa tạo ('Dispatch'), chuyển cho nó kiểu hành động tương ứng mà chúng tôi muốn thực thi. Phía sau, chức năng điều phối sẽ kết nối với bộ giảm tốc và thực sự sửa đổi trạng thái.
<button onClick={() => dispatch({type: 'ADD'})}>Add 1</button>

Nó hơi nhiều hơn một chút so với việc sử dụng useState, nhưng dù sao thì useReducer cũng không phức tạp như vậy.

Tóm lại, chúng ta chỉ cần:

  • Một bộ giảm tốc, đó là chức năng sẽ hợp nhất tất cả các thay đổi trạng thái có thể xảy ra
  • Một chức năng điều phối, sẽ gửi các hành động sửa đổi đến bộ giảm tốc.

Vấn đề ở đây là các phần tử giao diện người dùng sẽ không thể cập nhật trạng thái trực tiếp như chúng đã làm trước đây khi gọi setState với một giá trị. Bây giờ họ sẽ phải gọi một loại hành động và đi qua trình giảm bớt, điều này làm cho việc quản lý nhà nước trở nên mô-đun và dễ dự đoán hơn. ;)

Còn về Redux?

Redux là một thư viện đã có từ rất lâu đời và được sử dụng rộng rãi trong môi trường React.

Redux là một công cụ giải quyết cả hai vấn đề đã đề cập trước đây (khoan chân và hành vi trạng thái không thể đoán trước khi thay đổi trạng thái thường xuyên và phức tạp).

Điều quan trọng cần đề cập là Redux là một thư viện bất khả tri, có nghĩa là nó có thể được triển khai trên bất kỳ ứng dụng front end nào, không chỉ React.

Bộ công cụ Redux rất giống với những gì chúng ta vừa thấy với useReducer, nhưng có thêm một số thứ. Có ba khối xây dựng chính trong Redux:

  • Cửa hàng - một đối tượng chứa dữ liệu trạng thái ứng dụng
  • Bộ giảm thiểu - một hàm trả về một số dữ liệu trạng thái, được kích hoạt bởi một loại hành động
  • Một hành động - một đối tượng cho bộ giảm tốc biết cách thay đổi trạng thái. Nó phải chứa một thuộc tính kiểu và nó có thể chứa một thuộc tính trọng tải tùy chọn

Triển khai Redux, ứng dụng mẫu của chúng tôi sẽ trông như thế này:

// App.js
import './App.scss'

import { Provider, useSelector, useDispatch } from 'react-redux'
import { addOne, subOne, addSome, subSome, reset } from './store/actions/count.actions'

import store from './store'

function App() {

  const dispatch = useDispatch()
  const count = useSelector(state => state.count)

  return (
    <Provider store={store}>
      <div className="App">
        <p>Count is: {count}</p>

        <div>
          <button onClick={() => dispatch(addOne())}>Add 1</button>
          
          <button onClick={() => dispatch(subOne())}>Decrease 1</button>

          <button onClick={() => dispatch(addSome(10))}>Add 10</button>
          <button onClick={() => dispatch(subSome(10))}>Decrease 10</button>

          <button onClick={() => dispatch(reset())}>Reset count</button>
        </div>
      </div>
    </Provider>
  )
}

export default App

Bên cạnh đó, bây giờ chúng ta sẽ cần một thư mục lưu trữ mới , với các tệp lưu trữ, trình giảm thiểu và hành động tương ứng của nó.

Cbdp2DJY9

// index.js (STORE)
import { createStore } from 'redux'
import CountReducer from './reducers/count.reducer'

export default createStore(CountReducer)
// count.reducer.js
import { ADD, SUB, ADDSOME, SUBSOME, RESET } from '../actions/count.actions'

const CountReducer = (state = { count: 0 }, action) => {
    switch (action.type) {
      case ADD: return { count: state.count + 1 }
      case SUB: return { count: state.count - 1 }
      case ADDSOME: return { count: state.count + action.payload }
      case SUBSOME: return { count: state.count - action.payload }
      case RESET: return { count: 0 }
      default: return state
    }
}

export default CountReducer
// count.actions.js
export const ADD = 'ADD'
export const addOne = () => ({ type: ADD })

export const SUB = 'SUB'
export const subOne = () => ({ type: SUB })

export const ADDSOME = 'ADDSOME'
export const addSome = (value) => ({
    type: ADDSOME,
    payload: value
})

export const SUBSOME = 'SUBSOME'
export const subSome = (value) => ({
    type: SUBSOME,
    payload: value
})

export const RESET = 'RESET'
export const reset = () => ({ type: RESET })

Đây là nhiều hơn những gì chúng ta đã thấy trước đây (đó là những gì Redux chủ yếu bị chỉ trích), vì vậy hãy chia nó thành nhiều phần:

Như tôi đã đề cập, Redux là một thư viện bên ngoài, vì vậy trước bất kỳ thứ gì chúng ta cần cài đặt nó bằng cách chạy npm i redux react-redux. reduxsẽ mang đến các chức năng cốt lõi mà chúng ta cần để quản lý trạng thái của mình và react-reduxsẽ cài đặt một số móc mát để dễ dàng đọc và sửa đổi trạng thái từ các thành phần của chúng ta.

Bây giờ, điều đầu tiên là cửa hàng . Trong Redux, cửa hàng là thực thể có tất cả thông tin trạng thái ứng dụng. Nhờ Redux, chúng tôi có thể truy cập cửa hàng từ bất kỳ thành phần nào chúng tôi muốn (giống như với ngữ cảnh).

Để tạo một cửa hàng, chúng tôi nhập createStorehàm và chuyển hàm này làm đầu vào.

Biết rằng bạn cũng có thể kết hợp các bộ giảm giá khác nhau và chuyển nó đến cùng một cửa hàng trong trường hợp bạn muốn tách mối quan tâm thành các bộ giảm giá khác nhau.

import { createStore } from 'redux'
import CountReducer from './reducers/count.reducer'

export default createStore(CountReducer)
  • Sau đó, có bộ giảm tốc , hoạt động giống hệt như cái mà chúng ta đã thấy với useReducer. Nó lấy trạng thái mặc định và một hành động làm tham số, sau đó bên trong nó có một câu lệnh switch để đọc loại hành động, thực hiện sửa đổi trạng thái tương ứng và trả về trạng thái đã cập nhật.
import { ADD, SUB, ADDSOME, SUBSOME, RESET } from '../actions/count.actions'

const CountReducer = (state = { count: 0 }, action) => {
    switch (action.type) {
      case ADD: return { count: state.count + 1 }
      case SUB: return { count: state.count - 1 }
      case ADDSOME: return { count: state.count + action.payload }
      case SUBSOME: return { count: state.count - action.payload }
      case RESET: return { count: 0 }
      default: return state
    }
}

export default CountReducer
  • Sau đó đến các hành động . Các hành động là những gì chúng ta sẽ sử dụng để cho bộ giảm tải biết cách cập nhật trạng thái. Trong đoạn mã, bạn có thể thấy rằng đối với mỗi hành động, chúng tôi đang khai báo các hằng số để sử dụng chúng thay vì các chuỗi đơn giản (đây là một phương pháp hay để cải thiện khả năng bảo trì) và các hàm trả về chỉ một kiểu hoặc một kiểu và một trọng tải. Các chức năng này là những gì chúng ta sẽ gửi từ thành phần của mình để thay đổi trạng thái. ;)

Lưu ý rằng tôi đã thay đổi ví dụ một chút để hiển thị trọng tải có nghĩa là gì khi nói về các hành động. Trong trường hợp chúng ta muốn truyền một tham số từ thành phần khi chúng ta gửi một hành động, trọng tải sẽ là nơi chứa thông tin đó .

Trong ví dụ này, bạn có thể thấy rằng bây giờ chúng ta có thể chuyển trực tiếp từ thành phần số mà chúng ta muốn thêm / rút ngắn khi chúng ta gọi ADDSOME / SUBSOME.

export const ADD = 'ADD'
export const addOne = () => ({ type: ADD })

export const SUB = 'SUB'
export const subOne = () => ({ type: SUB })

export const ADDSOME = 'ADDSOME'
export const addSome = value => ({
    type: ADDSOME,
    payload: value
})

export const SUBSOME = 'SUBSOME'
export const subSome = value => ({
    type: SUBSOME,
    payload: value
})

export const RESET = 'RESET'
export const reset = () => ({ type: RESET })
  • Và cuối cùng là thành phần của chúng tôi. Ở đây chúng tôi có 3 điều cần lưu ý:

Đầu tiên, chúng tôi có một thành phần nhà cung cấp nhận cửa hàng làm đạo cụ. Đây là thứ cấp quyền truy cập vào cửa hàng của chúng tôi từ tất cả các thành phần được bao bọc trong đó.

Sau đó, chúng ta có một hook được gọi là useDispatch () (mà chúng ta sẽ sử dụng để gửi các hành động) và một hook khác được gọi là useSelector () (mà chúng ta sẽ sử dụng để đọc trạng thái từ cửa hàng).

Cuối cùng, hãy lưu ý rằng chúng tôi đang điều hành các hàm mà chúng tôi đã khai báo trên tệp hành động và chuyển một giá trị làm đầu vào khi nó tương ứng. Giá trị này là những gì các hành động thực hiện dưới dạng tải trọng và những gì trình giảm bớt sẽ sử dụng để sửa đổi trạng thái. ;)

import './App.scss'

import { useSelector, useDispatch } from 'react-redux'
import { addOne, subOne, addSome, subSome, reset } from './store/actions/count.actions'

function App() {

  const dispatch = useDispatch()
  const count = useSelector(state => state.count)

  return (
      <div className="App">
        <p>Count is: {count}</p>

        <div>
          <button onClick={() => dispatch(addOne())}>Add 1</button>
          
          <button onClick={() => dispatch(subOne())}>Decrease 1</button>

          <button onClick={() => dispatch(addSome(10))}>Add 10</button>
          <button onClick={() => dispatch(subSome(10))}>Decrease 10</button>

          <button onClick={() => dispatch(reset())}>Reset count</button>
        </div>
      </div>
  )
}

export default App

Redux là một công cụ tốt có thể giải quyết hai vấn đề cùng một lúc (khoan trụ và thay đổi trạng thái phức tạp). Tuy nhiên, nó tạo ra rất nhiều bản soạn sẵn và khiến việc quản lý nhà nước trở thành một chủ đề khó tìm hiểu hơn, đặc biệt là khi xử lý các tệp và thực thể khác nhau như hành động, bộ giảm, cửa hàng ...

Một điều quan trọng cần đề cập ở đây là những công cụ hoặc cách quản lý trạng thái này không loại trừ lẫn nhau, chúng có thể và có lẽ nên được sử dụng cùng một lúc, mỗi công cụ để giải quyết vấn đề cụ thể mà chúng giỏi.

Trong trường hợp của Redux, vấn đề đó đang xử lý trạng thái toàn cục (có nghĩa là trạng thái ảnh hưởng đến toàn bộ ứng dụng của bạn hoặc một phần rất lớn của nó). Sẽ không hợp lý nếu sử dụng Redux để xử lý một bộ đếm như ví dụ của chúng tôi hoặc việc mở và đóng một phương thức.

Một quy tắc vàng tốt là useState cho trạng thái thành phần, Redux cho trạng thái ứng dụng .

Các lựa chọn thay thế cho Redux

Nếu chủ đề này chưa đủ phức tạp đối với bạn, trong vài năm gần đây, rất nhiều thư viện mới đã xuất hiện như những lựa chọn thay thế cho Redux, mỗi thư viện có cách tiếp cận riêng để quản lý nhà nước.

Để có một cái nhìn tổng quan, chúng ta hãy nhanh chóng tìm hiểu chúng.

Bộ công cụ Redux

Bộ công cụ Redux là một thư viện được xây dựng trên nền Redux, nhằm mục đích loại bỏ một số phức tạp và bảng soạn sẵn mà Redux tạo ra.

Bộ công cụ Redux được xây dựng dựa trên hai thứ:

  • Một cửa hàng , hoạt động giống hệt như một cửa hàng Redux đơn thuần
  • các lát cắt cô đọng các hành động và bộ giảm Redux đơn giản thành một thứ duy nhất

Triển khai Bộ công cụ Redux, ứng dụng mẫu của chúng tôi sẽ trông giống như sau:

// App.js
import './App.scss'

import { useSelector, useDispatch } from 'react-redux'
import { addOne, subOne, addSome, subSome, reset } from './store/slices/count.slice'

function App() {

  const dispatch = useDispatch()
  const count = useSelector(state => state.counter.count)

  return (
      <div className="App">
        <p>Count is: {count}</p>

        <div>
          <button onClick={() => dispatch(addOne())}>Add 1</button>
          
          <button onClick={() => dispatch(subOne())}>Decrease 1</button>

          <button onClick={() => dispatch(addSome(10))}>Add 10</button>
          <button onClick={() => dispatch(subSome(10))}>Decrease 10</button>

          <button onClick={() => dispatch(reset())}>Reset count</button>
        </div>
      </div>
  )
}

export default App
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { Provider } from 'react-redux'
import store from './store/index'

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
)
// Index.jsx (STORE)
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './slices/count.slice'

export const store = configureStore({
  reducer: {
      counter: counterReducer
  },
})

export default store
// count.slice.jsx
import { createSlice } from '@reduxjs/toolkit'

const initialState = { count: 0 }

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    addOne: state => {state.count += 1},
    subOne: state => {state.count -= 1},
    addSome: (state, action) => {state.count += action.payload},
    subSome: (state, action) => {state.count -= action.payload},
    reset: state => {state.count = 0}
  },
})

export const { addOne, subOne, addSome, subSome, reset } = counterSlice.actions

export default counterSlice.reducer

Đầu tiên chúng ta cần cài đặt nó bằng cách chạynpm install @reduxjs/toolkit react-redux

Trên cửa hàng của chúng tôi, chúng tôi nhập configureStorehàm từ bộ công cụ Redux và tạo cửa hàng bằng cách gọi hàm này và chuyển cho nó một đối tượng có bộ giảm tốc, bản thân nó là một đối tượng có chứa một lát cắt.

export const store = configureStore({
  reducer: {
      counter: counterReducer
  },
})
  • Một lát cắt , như tôi đã đề cập, là một cách để cô đọng các hành động và bộ giảm vào cùng một thứ. Chúng tôi nhập createSlice hàm từ bộ công cụ Redux, sau đó khai báo trạng thái ban đầu và khởi tạo lát cắt.

Cái này sẽ nhận dưới dạng các tham số tên của lát cắt, trạng thái ban đầu và các chức năng mà chúng tôi sẽ gửi từ các thành phần của mình để sửa đổi trạng thái.

Lưu ý rằng không có hành động nào ở đây. Giao diện người dùng sẽ gọi trực tiếp các hàm giảm thiểu. Đó là sự phức tạp mà bộ công cụ Redux "lấy đi".

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    addOne: state => {state.count += 1},
    subOne: state => {state.count -= 1},
    addSome: (state, action) => {state.count += action.payload},
    subSome: (state, action) => {state.count -= action.payload},
    reset: state => {state.count = 0}
  },
})
  • Trên index.js, chúng tôi bao bọc ứng dụng của mình xung quanh thành phần nhà cung cấp để chúng tôi có thể truy cập trạng thái từ bất kỳ đâu.
    <Provider store={store}>
      <App />
    </Provider>
  • Và cuối cùng, từ thành phần của chúng tôi, chúng tôi đọc trạng thái và gửi các chức năng sửa đổi bằng cách sử dụng hook giống như với Redux đơn giản.
function App() {

  const dispatch = useDispatch()
  const count = useSelector(state => state.counter.count)

  return (
      <div className="App">
        <p>Count is: {count}</p>

        <div>
          <button onClick={() => dispatch(addOne())}>Add 1</button>
          
          <button onClick={() => dispatch(subOne())}>Decrease 1</button>

          <button onClick={() => dispatch(addSome(10))}>Add 10</button>
          <button onClick={() => dispatch(subSome(10))}>Decrease 10</button>

          <button onClick={() => dispatch(reset())}>Reset count</button>
        </div>
      </div>
  )
}

Bộ công cụ Redux nhằm mục đích trở thành một cách đơn giản hơn để xử lý Redux, nhưng theo ý kiến ​​của tôi, nó vẫn gần như giống với bản soạn sẵn và không có nhiều sự khác biệt với Redux đơn giản.

Đề cập cho Redux Thunk và Redux Saga

Redux thunkRedux Saga là hai thư viện phần mềm trung gian phổ biến khác được sử dụng cùng với Redux.

Cụ thể, cả Thunk và Saga đều được sử dụng khi đối phó với các tác dụng phụ hoặc nhiệm vụ không đồng bộ.

Giật

2CYCmD92D

Recoil là một thư viện quản lý trạng thái mã nguồn mở dành riêng cho React được xây dựng bởi Facebook (hoặc Meta, bất cứ điều gì ...). Theo trang web của họ, Recoil được xây dựng để "tối thiểu và dễ phản hồi", theo nghĩa nó trông giống như mã React đơn giản.

Độ giật được dựa trên ý tưởng của các nguyên tử . Trích dẫn tài liệu của họ,

"Nguyên tử đại diện cho một phần trạng thái. Nguyên tử có thể được đọc và ghi vào từ bất kỳ thành phần nào. Các thành phần đọc giá trị của nguyên tử được đăng ký ngầm với nguyên tử đó, vì vậy bất kỳ cập nhật nguyên tử nào sẽ dẫn đến kết xuất lại tất cả các thành phần đăng ký vào nguyên tử đó ”.

Sử dụng Recoil, ứng dụng mẫu của chúng tôi sẽ trông như thế này:

// App.js
import countState from './recoil/counter.atom'
import './App.scss'

import { useRecoilState } from 'recoil'

function App() {

  const [count, setCount] = useRecoilState(countState)

  return (
      <div className="App">
        <p>Count is: {count}</p>

        <div>
          <button onClick={() => setCount(count+1)}>Add 1</button>
          
          <button onClick={() => setCount(count-1)}>Decrease 1</button>

          <button onClick={() => setCount(count+10)}>Add 10</button>
          <button onClick={() => setCount(count-10)}>Decrease 10</button>

          <button onClick={() => setCount(0)}>Reset count</button>
        </div>
      </div>
  )
}

export default App
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { RecoilRoot } from 'recoil'

ReactDOM.render(
  <React.StrictMode>
    <RecoilRoot>
      <App />
    </RecoilRoot>
  </React.StrictMode>,
  document.getElementById('root')
)
// counter.atom.jsx
import { atom } from 'recoil'

const countState = atom({
  key: 'countState', // unique ID (with respect to other atoms/selectors)
  default: 0 // default value (aka initial value)
})

export default countState

Như bạn có thể thấy ngay lập tức, đây là bản soạn thảo ít hơn rất nhiều so với Redux. = D

Đầu tiên, chúng tôi cài đặt nó bằng cách chạynpm install recoil

Các thành phần sử dụng trạng thái giật cần RecoilRootphải xuất hiện ở đâu đó trong cây mẹ. Vì vậy, chúng tôi kết hợp ứng dụng của mình với nó.

  <React.StrictMode>
    <RecoilRoot>
      <App />
    </RecoilRoot>
  </React.StrictMode>
  • Sau đó, chúng tôi khai báo nguyên tử của mình , chỉ là một đối tượng chứa khóa và giá trị mặc định:
const countState = atom({
  key: 'countState', // unique ID (with respect to other atoms/selectors)
  default: 0 // default value (aka initial value)
})
  • Cuối cùng, trong thành phần của chúng tôi, chúng tôi nhập hook useRecoilStatevà khai báo trạng thái của chúng tôi với nó, chuyển cho nó khóa duy nhất mà chúng tôi vừa khai báo trong nguyên tử của mình.
const [count, setCount] = useRecoilState(countState)

Như bạn có thể thấy, điều này trông thực sự giống với một hook useState thông thường. Reactish ... = P

Và từ giao diện người dùng của chúng tôi, chúng tôi chỉ gọi setCounthàm để cập nhật trạng thái của chúng tôi.

<button onClick={() => setCount(count+1)}>Add 1</button>

Tối thiểu và rất dễ sử dụng. Recoil vẫn chỉ là thử nghiệm và không được sử dụng rộng rãi, nhưng bạn có thể thấy các nhà phát triển trên khắp thế giới sẽ sử dụng công cụ này như thế nào.

Jotai

Jotai là một thư viện quản lý trạng thái mã nguồn mở được xây dựng cho React được lấy cảm hứng từ Recoil. Nó khác với Recoil ở chỗ tìm kiếm một API tối giản hơn - nó không sử dụng các khóa chuỗi và hướng tới TypeScript.

Tương tự như với Recoil, Jotai sử dụng các nguyên tử. Một nguyên tử đại diện cho một phần của trạng thái. Tất cả những gì bạn cần là chỉ định một giá trị ban đầu, có thể là các giá trị nguyên thủy như chuỗi và số, đối tượng và mảng. Sau đó, trong các thành phần của bạn, bạn sử dụng nguyên tử đó, và trên mỗi thay đổi nguyên tử, thành phần đó sẽ hiển thị lại.

Sử dụng Jotai, ứng dụng mẫu của chúng tôi trông như thế này:

// App.js
import './App.scss'

import { useAtom } from 'jotai'

function App() {

  const [count, setCount] = useAtom(countAtom)

  return (
      <div className="App">
        <p>Count is: {count}</p>

        <div>
          <button onClick={() => setCount(count+1)}>Add 1</button>
          
          <button onClick={() => setCount(count-1)}>Decrease 1</button>

          <button onClick={() => setCount(count+10)}>Add 10</button>
          <button onClick={() => setCount(count-10)}>Decrease 10</button>

          <button onClick={() => setCount(0)}>Reset count</button>
        </div>
      </div>
  )
}

export default App
// counter.atom.jsx
import { atom } from 'jotai'

const countAtom = atom(0)

export default countAtom

Như bạn có thể thấy, nó thậm chí còn tối thiểu hơn Recoil.

Chúng tôi cài đặt nó bằng cách chạynpm install jotai

Sau đó, chúng tôi khai báo một nguyên tử với giá trị mặc định:

const countAtom = atom(0)
  • Và sử dụng nó với thành phần của chúng tôi bằng cách sử dụng useAtom:
const [count, setCount] = useAtom(countAtom)

Thực sự tốt đẹp và đơn giản!

Zustand

Zustand là một thư viện quản lý trạng thái mã nguồn mở khác được xây dựng cho React. Nó được lấy cảm hứng từ Flux, một thư viện được sử dụng rộng rãi trước khi Redux xuất hiện và nó nhằm mục đích

"một giải pháp quản lý nhà nước nhỏ gọn, nhanh chóng, không có ý kiến ​​và có thể mở rộng với một API thoải mái dựa trên các hook và hầu như không có bảng soạn sẵn".

Zustand sử dụng một cửa hàng theo cách tương tự như Redux, nhưng với sự khác biệt ở Zustand, cửa hàng bây giờ là một cái móc và nó cần ít bản ghi sẵn hơn nhiều.

Sử dụng Zustand, ứng dụng mẫu của chúng tôi sẽ trông như thế này:

// App.js
import './App.scss'
import useStore from './store'

function App() {

  const count = useStore(state => state.count)
  const { addOne, subOne, add10, sub10, reset } = useStore(state => state)

  return (
      <div className="App">
        <p>Count is: {count}</p>

        <div>
            <button onClick={() => addOne()}>Add 1</button>
          
          <button onClick={() => subOne()}>Decrease 1</button>

          <button onClick={() => add10()}>Add 10</button>
          <button onClick={() => sub10()}>Decrease 10</button>

          <button onClick={() => reset()}>Reset count</button>
        </div>
      </div>
  )
}

export default App
// Index.jsx (STORE)
import create from 'zustand'

const useStore = create(set => ({
  count: 0,
  addOne: () => set(state => ({count: state.count += 1})),
  subOne: () => set(state => ({count: state.count -= 1})),
  add10: () => set(state => ({count: state.count += 10})),
  sub10: () => set(state => ({count: state.count -= 10})),
  reset: () => set({count: 0})
}))

export default useStore

Chúng tôi cài đặt nó bằng cách chạynpm install zustand

Chúng tôi tạo một cửa hàng với createchức năng mà chúng tôi đã nhập từ Zustand. Bên trong, chúng tôi đặt trạng thái mặc định và các chức năng chúng tôi sẽ sử dụng để sửa đổi trạng thái.

const useStore = create(set => ({
  count: 0,
  addOne: () => set(state => ({count: state.count += 1})),
  subOne: () => set(state => ({count: state.count -= 1})),
  add10: () => set(state => ({count: state.count += 10})),
  sub10: () => set(state => ({count: state.count -= 10})),
  reset: () => set({count: 0})
}))
  • Sau đó, trong thành phần của chúng tôi, chúng tôi nhập cửa hàng mà chúng tôi vừa tạo và đọc trạng thái và sửa đổi các chức năng từ nó theo cách sau:
  const count = useStore(state => state.count)
  const { addOne, subOne, add10, sub10, reset } = useStore(state => state)

Giao diện người dùng của chúng tôi có thể gọi các chức năng sửa đổi giống như sau:

<button onClick={() => addOne()}>Add 1</button>

Bạn có thể thấy Zustand xuất phát từ những khái niệm tương tự về Redux, với cách tiếp cận đơn giản và gọn gàng hơn nhiều.

Phần kết luận

Quản lý nhà nước là một trong những chủ đề phức tạp nhất khi nói đến phát triển front end. Và bạn có thể thấy có bao nhiêu người đã cố gắng làm cho nó hoạt động theo cách có thể dự đoán được và có thể mở rộng, nhưng cũng theo những cách sạch sẽ và dễ sử dụng.

Đặc biệt trong những năm gần đây, rất nhiều công cụ tốt đã đưa ra những cách giải quyết hay trong công tác quản lý nhà nước.

Tuy nhiên, với tư cách là nhà phát triển, chúng tôi phải lưu ý rằng Redux và các thư viện khác được tạo ra để giải quyết các vấn đề quản lý nhà nước cụ thể, đặc biệt trong các ứng dụng thực sự lớn, phức tạp và được sử dụng nhiều.

Tôi nghĩ rằng nếu bạn không gặp phải những vấn đề này, thì thực sự không cần phải thêm bảng soạn sẵn và làm phức tạp mã của bạn. Ngay cả với các thư viện hiện đại hầu như không thêm bản ghi sẵn.

Bản thân React là một thư viện rất mạnh và vững chắc, và các công cụ như useState, useReducer và useContext là khá đủ để giải quyết hầu hết các vấn đề. Vì vậy, tôi sẽ bám vào những điều cơ bản trừ khi vì một lý do nào đó mà những điều cơ bản không còn đủ nữa.

Khi cần một thư viện quản lý nhà nước mạnh mẽ và cụ thể hơn, tôi nghĩ sự lựa chọn là vấn đề quyết định giữa độ tin cậy và tính đơn giản.

Redux là thư viện dành cho người lớn và được sử dụng nhiều nhất, đi kèm với rất nhiều tài liệu, cộng đồng trực tuyến và các lỗi trước đó được tìm thấy và giải quyết với mỗi bản phát hành mới.

Điều tồi tệ của nó là, với tư cách là các nhà phát triển, nó trình bày cho chúng ta một số khái niệm mới mà chúng ta phải học và suy nghĩ. Chúng tôi cũng cần thêm khá nhiều mã chỉ để làm cho nó hoạt động và nó có thể thêm phức tạp hơn những vấn đề mà nó giúp giải quyết.

Ngược lại, các thư viện hiện đại như chúng ta đã thấy đơn giản hơn nhiều và đi thẳng vào vấn đề, nhưng không được sử dụng và thử nghiệm rộng rãi, và vẫn chỉ là thử nghiệm.

Nhưng đối với những gì chúng ta có thể thấy vào lúc này, có vẻ như chỉ là vấn đề thời gian cho đến khi một hoặc một số trong số chúng dẫn đầu và trở thành công cụ được sử dụng rộng rãi hơn.

Đó là nó! Tôi hy vọng bạn thích bài viết và học được điều gì đó mới.
Nếu bạn muốn, bạn cũng có thể theo dõi tôi trên linkedin hoặc twitter .
Chúc mừng và hẹn gặp lại các bạn trong những chương trình tiếp theo!

Nguồn: https://www.freecodecamp.org/news/how-to-manage-state-in-a-react-app/

#react #hooks #redux