React - Làm thế nào để buộc một thành phần hàm hiển thị?


84

Tôi có một thành phần chức năng và tôi muốn buộc nó hiển thị lại.

Làm thế nào tôi có thể làm như vậy?
Vì không có phiên bản nào thisnên tôi không thể gọi this.forceUpdate().


không, một thành phần không trạng thái không có trạng thái. Thay vào đó, hãy sử dụng một lớp học
TryToImprove, 15/09/17

2
Bạn thực sự có nghĩa là "thành phần không trạng thái " chứ không phải "thành phần chức năng" ?
Chris

2
Để cập nhật một thành phần không trạng thái, các đạo cụ được chuyển cần phải thay đổi.
Mushanthrax

bên cạnh các đạo cụ, bạn có thể sử dụng hook useState và các thành phần sẽ được hiển thị lại khi nó thay đổi
Hamid Shoja

Câu trả lời:


134

🎉 Bây giờ bạn có thể sử dụng React hooks

Sử dụng các móc phản ứng, bây giờ bạn có thể gọi useState()trong thành phần hàm của mình.

useState()sẽ trả về một mảng gồm 2 thứ:
1. Một giá trị, đại diện cho trạng thái hiện tại.
2. Bộ định vị của nó. Sử dụng nó để cập nhật giá trị.

Việc cập nhật giá trị bằng trình thiết lập của nó sẽ buộc thành phần hàm của bạn hiển thị lại ,
giống như forceUpdate:

import React, { useState } from 'react';

//create your forceUpdate hook
function useForceUpdate(){
    const [value, setValue] = useState(0); // integer state
    return () => setValue(value => ++value); // update the state to force render
}

function MyComponent() {
    // call your hook here
    const forceUpdate = useForceUpdate();

    return (
        <div>
            {/*Clicking on the button will force to re-render like force update does */}
            <button onClick={forceUpdate}>
                Click to re-render
            </button>
        </div>
    );
}

Bạn có thể tìm thấy một bản demo ở đây .

Thành phần trên sử dụng một hàm hook tùy chỉnh ( useForceUpdate) sử dụng một hook trạng thái boolean ( useState). Nó chuyển đổi trạng thái boolean và do đó yêu cầu React chạy lại chức năng kết xuất.

BIÊN TẬP

Trong phiên bản cũ của câu trả lời này, đoạn mã đã sử dụng giá trị boolean và chuyển nó vào forceUpdate(). Bây giờ tôi đã chỉnh sửa câu trả lời của mình, đoạn mã sử dụng một số thay vì boolean.

Tại sao ? (bạn sẽ hỏi tôi)

Bởi vì một lần nó xảy ra với tôi rằng my forceUpdate()đã được gọi hai lần sau đó từ 2 sự kiện khác nhau, và do đó nó đang gửi lại giá trị boolean ở trạng thái ban đầu và thành phần không bao giờ được hiển thị.

Bởi vì trong useStatesetter của '( setValueở đây), hãy Reactso sánh trạng thái trước đó với trạng thái mới và chỉ hiển thị nếu trạng thái khác.


3
Không có gì trên trang đó có bất kỳ thông tin nào về việc sử dụng Hooks để gọi forceUpdate.
jdelman 21/1218

1
Hiện tại, bạn nói đúng, nó tốt hơn, bởi vì, ngay cả những móc khó khăn vẫn chưa được phát hành, bạn vẫn có thể sử dụng nó trong bản beta. Nhưng một khi chúng được phát hành, không có lý do gì thành phần lớp sẽ tốt hơn. Sử dụng hook làm cho mã sạch hơn so với thành phần lớp, như video bên dưới trong reactconf cho thấy. Dù sao, câu hỏi là nếu điều này là có thể. Câu trả lời bây giờ thay đổi từ "Không" thành "Có" vì dấu móc. youtube.com/watch?v=wXLf18DsV-I
Yairopro

1
Xin chào @DanteTheSmith. Theo "Mức cao nhất", điều đó có nghĩa là các hook không được gọi từ bên trong một điều kiện hoặc vòng lặp, như bạn đã nói. Nhưng tôi có thể nói với bạn rằng bạn có thể gọi chúng từ bên trong một hàm khác. Và điều đó có nghĩa là tạo một hook tùy chỉnh. Dan Abramov, như ông trình bày Phản ứng móc trong Phản ứng conf, chứng minh rõ ràng rằng đây là cách sạch nhất và tốt nhất logic cổ phiếu giữa các thành phần chức năng: youtu.be/dpw9EHDh2bM?t=2753
Yairopro

1
Không cần phải chuyển đổi bất kỳ trạng thái "để buộc kết xuất". Bạn tạo ra một ấn tượng sai lầm rằng React "so sánh" các giá trị trạng thái trước và sau để quyết định xem nó có cần hiển thị lại hay không. Trong khi nó chắc chắn không.
urndre

1
@meandre Có nó chắc chắn so sánh. Chúng ta đang nói về useStatehook, chứ không phải class ' setStatethực sự không tạo ra một so sánh (trừ khi bạn triển khai phương thức shouldUpdate). Xem các bản demo cùng tôi được đăng, nhưng với một giá trị tĩnh sử dụng cho setState, nó không làm nữa: codesandbox.io/s/determined-rubin-8598l
Yairopro

47

Cập nhật react v16.8 (bán lại vào ngày 16 tháng 2 năm 2019)

Kể từ khi phản ứng 16.8 được phát hành với hook , các thành phần chức năng giờ đây có khả năng giữ lâu dài state. Với khả năng mà bạn có thể bây giờ bắt chước một forceUpdate:

Lưu ý rằng phương pháp này nên được xem xét lại và trong hầu hết các trường hợp khi bạn cần cập nhật, có thể bạn đã làm sai.


Trước khi phản ứng 16.8.0

Không, bạn không thể, các thành phần chức năng State-Less chỉ bình thường functionstrả về jsx, bạn không có bất kỳ quyền truy cập nào vào các phương thức vòng đời React vì bạn không mở rộng từ React.Component.

Hãy nghĩ về hàm-thành phần như rendermột phần phương thức của các thành phần lớp.


ofc bạn có thể. thay đổi đạo cụ mà đến với nó
Marián Zeke Šedaj

5
điều đó không buộc phải kết xuất lại, đó chỉ là kết xuất bình thường. khi bạn muốn buộc kết xuất, thường là trường hợp bạn muốn chạy phương thức kết xuất khi nó không được thiết kế để chạy, chẳng hạn như khi không có thay đổi propshoặc mới state. bạn không thể bắt buộc chức năng kết xuất vì không có renderchức năng nào trên các thành phần không trạng thái. các thành phần không trạng thái không phải extends React.Componentchúng chỉ là các hàm đơn giản trả về jsx.
Sagiv bg

Đạo cụ cho "khi bạn cần cập nhật có thể bạn đang làm sai điều gì đó" - Tôi biết đó là trường hợp, nhưng điều này chỉ nhắc nhở tôi xem xét kỹ hơn về useEffect hook của mình.
Methodician

12

Câu hỏi thường gặp chính thức ( https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate ) hiện khuyến nghị cách này nếu bạn thực sự cần làm điều đó:

  const [ignored, forceUpdate] = useReducer(x => x + 1, 0);

  function handleClick() {
    forceUpdate();
  }

Tôi chưa bao giờ biết điều đó
Charith Jayasanka

9
và bạn có thể làm cho mã của mình ngắn hơn 7 byte và không tạo biến không sử dụng:const [, forceUpdate] = useReducer(x => x + 1, 0);
Konstantin Smolyanin

7

Tôi đã sử dụng thư viện của bên thứ ba có tên là use-force-update để buộc hiển thị các thành phần chức năng phản ứng của mình. Làm việc như một sự quyến rũ. Chỉ cần sử dụng nhập gói trong dự án của bạn và sử dụng như thế này.

import useForceUpdate from 'use-force-update';

const MyButton = () => {

  const forceUpdate = useForceUpdate();

  const handleClick = () => {
    alert('I will re-render now.');
    forceUpdate();
  };

  return <button onClick={handleClick} />;
};

2
Để tiết kiệm cho bạn một cú nhấp chuột - useForceUpdatesử dụng useCallbacknhư đã đề cập trong các câu trả lời khác. Lib này chỉ là một lib tiện ích giúp bạn tiết kiệm một vài lần gõ phím.
asyncwait

oh Cảm ơn bạn. Tôi không biết điều đó. :)
Charith Jayasanka

6

Tuyên bố từ chối trách nhiệm: KHÔNG PHẢI TRẢ LỜI CHO VẤN ĐỀ.

Để lại một ghi chú quan trọng ở đây:

Nếu bạn đang cố gắng cập nhật một thành phần không trạng thái, rất có thể thiết kế của bạn đã xảy ra lỗi.

Hãy xem xét các trường hợp sau:

  1. Truyền một setter (setState) cho một thành phần con có thể thay đổi trạng thái và khiến thành phần mẹ hiển thị lại.
  2. Cân nhắc nâng trạng thái lên
  3. Cân nhắc đưa trạng thái đó vào cửa hàng Redux của bạn, điều này có thể tự động buộc hiển thị lại trên các thành phần được kết nối.

1
Tôi gặp trường hợp cần tắt các bản cập nhật thành phần và buộc nó chỉ khi tôi muốn (là thước đo di chuyển, giá trị cập nhật của nó mỗi lần di chuyển và các bản cập nhật gây ra hiện tượng nhấp nháy). Vì vậy, tôi quyết định sử dụng các lớp trên thành phần này và tôi khuyên rằng tất cả các thành phần cần kiểm soát sâu về hành vi kết xuất nên được thực hiện trong các lớp, vì hiện tại hook không cung cấp khả năng kiểm soát tốt đối với hành vi này. (phiên bản React hiện tại là 16.12)
Michael Wallace

Tôi cũng nghĩ như vậy nhưng, tôi muốn có một bản sửa lỗi nhanh chóng vì vậy tôi đã sử dụng buộc cập nhật.
Charith Jayasanka

Trong thế giới thực, có những công dụng cho nó. Không có gì là hoàn hảo và nếu bạn muốn đưa phần mềm ra khỏi cửa, bạn nên biết cách biến mọi thứ thành hiện thực khi người khác vặn chúng.
Brain2000

1

Điều này có thể được thực hiện mà không cần sử dụng hook rõ ràng với điều kiện bạn thêm một chỗ dựa vào thành phần của mình và một trạng thái vào thành phần mẹ của thành phần không trạng thái:

const ParentComponent = props => {
  const [updateNow, setUpdateNow] = useState(true)

  const updateFunc = () => {
    setUpdateNow(!updateNow)
  }

  const MyComponent = props => {
    return (<div> .... </div>)
  }

  const MyButtonComponent = props => {
    return (<div> <input type="button" onClick={props.updateFunc} />.... </div>)
  }

  return (
    <div> 
      <MyComponent updateMe={updateNow} />
      <MyButtonComponent updateFunc={updateFunc}/>
    </div>
  )
}

1

Câu trả lời được chấp nhận là tốt. Chỉ để làm cho nó dễ hiểu hơn.

Thành phần ví dụ:

export default function MyComponent(props) {

    const [updateView, setUpdateView] = useState(0);

    return (
        <>
            <span style={{ display: "none" }}>{updateView}</span>
        </>
    );
}

Để buộc kết xuất, hãy gọi mã bên dưới:

setUpdateView((updateView) => ++updateView);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.