Tôi có một đối tượng bên ngoài (đối với thành phần), có thể quan sát được mà tôi muốn lắng nghe những thay đổi trên đó. Khi đối tượng được cập nhật, nó phát ra các sự kiện thay đổi và sau đó tôi muốn kết xuất thành phần khi phát hiện bất kỳ thay đổi nào.
Với cấp cao nhất, React.render
điều này là có thể, nhưng trong một thành phần thì nó không hoạt động (điều này có ý nghĩa gì đó vì render
phương thức chỉ trả về một đối tượng).
Đây là một ví dụ về mã:
export default class MyComponent extends React.Component {
handleButtonClick() {
this.render();
}
render() {
return (
<div>
{Math.random()}
<button onClick={this.handleButtonClick.bind(this)}>
Click me
</button>
</div>
)
}
}
Việc nhấp vào nút nội bộ sẽ gọi this.render()
, nhưng đó không phải là điều thực sự khiến hiển thị xảy ra (bạn có thể thấy điều này đang hoạt động vì văn bản được tạo bởi {Math.random()}
không thay đổi). Tuy nhiên, nếu tôi chỉ đơn giản gọi this.setState()
thay vì this.render()
, nó hoạt động tốt.
Vì vậy, tôi đoán câu hỏi của tôi là: các thành phần React có cần phải có trạng thái để kết xuất không? Có cách nào để buộc thành phần cập nhật theo yêu cầu mà không thay đổi trạng thái không?
Trong thành phần của bạn, bạn có thể gọi this.forceUpdate()
để buộc kết xuất.
Tài liệu: https://facebook.github.io/react/docs/component-api.html
forceUpdate
nên tránh vì nó lệch khỏi tư duy React. Các tài liệu React trích dẫn một ví dụ về thời điểm forceUpdate
có thể được sử dụng:
Theo mặc định, khi trạng thái hoặc đạo cụ của thành phần thay đổi, thành phần của bạn sẽ hiển thị lại. Tuy nhiên, nếu những thay đổi này ngầm định (ví dụ: dữ liệu sâu bên trong một đối tượng thay đổi mà không thay đổi chính đối tượng) hoặc nếu phương thức render () của bạn phụ thuộc vào một số dữ liệu khác, bạn có thể nói với React rằng nó cần chạy lại render () bằng cách gọi forceUpdate ().
Tuy nhiên, tôi muốn đề xuất ý tưởng rằng ngay cả với các đối tượng lồng nhau sâu, forceUpdate
là không cần thiết. Bằng cách sử dụng nguồn dữ liệu bất biến, việc theo dõi các thay đổi trở nên rẻ; một thay đổi sẽ luôn dẫn đến một đối tượng mới, vì vậy chúng ta chỉ cần kiểm tra xem tham chiếu đến đối tượng đã thay đổi hay chưa. Bạn có thể sử dụng thư viện JS Immutable để triển khai các đối tượng dữ liệu bất biến vào ứng dụng của mình.
Thông thường, bạn nên cố gắng tránh tất cả việc sử dụng forceUpdate () và chỉ đọc từ this.props và this.state trong render (). Điều này làm cho thành phần của bạn trở nên "thuần túy" và ứng dụng của bạn đơn giản và hiệu quả hơn nhiều. forceUpdate ()
Thay đổi khóa của phần tử bạn muốn kết xuất lại sẽ hoạt động. Đặt giá đỡ khóa trên phần tử của bạn thông qua trạng thái và sau đó khi bạn muốn cập nhật trạng thái đặt để có khóa mới.
<Element key={this.state.key} />
Sau đó, một thay đổi xảy ra và bạn đặt lại khóa
this.setState({ key: Math.random() });
Tôi muốn lưu ý rằng điều này sẽ thay thế phần tử mà khóa đang thay đổi. Một ví dụ về nơi điều này có thể hữu ích là khi bạn có trường nhập tệp mà bạn muốn đặt lại sau khi tải lên hình ảnh.
Mặc dù câu trả lời thực sự cho câu hỏi của OP là forceUpdate()
tôi đã thấy giải pháp này hữu ích trong các tình huống khác nhau. Tôi cũng muốn lưu ý rằng nếu bạn thấy mình đang sử dụng, forceUpdate
bạn có thể muốn xem lại mã của mình và xem có cách nào khác để thực hiện mọi việc không.
LƯU Ý 1-9-2019:
Ở trên (thay đổi khóa) sẽ thay thế hoàn toàn phần tử. Nếu bạn thấy mình đang cập nhật khóa để thực hiện thay đổi, có thể bạn đang gặp sự cố ở nơi khác trong mã của mình. Sử dụng Math.random()
phím trong sẽ tạo lại phần tử với mỗi lần hiển thị. Tôi KHÔNG khuyên bạn nên cập nhật khóa như thế này vì react sử dụng khóa để xác định cách tốt nhất để hiển thị lại mọi thứ.
Trên thực tế, forceUpdate()
là giải pháp đúng duy nhất vì setState()
có thể không kích hoạt kết xuất lại nếu logic bổ sung được triển khai trong shouldComponentUpdate()
hoặc khi nó chỉ trả về false
.
Việc gọi
forceUpdate()
sẽrender()
được gọi trên thành phần, bỏ quashouldComponentUpdate()
. hơn...
setState()
sẽ luôn kích hoạt kết xuất lại trừ khi logic kết xuất có điều kiện được triển khai trongshouldComponentUpdate()
. hơn...
forceUpdate()
có thể được gọi từ bên trong thành phần của bạn bằng this.forceUpdate()
forceUpdate
được bằng cách làm theoCÁCH SAI : không sử dụng chỉ mục làm khóa
this.state.rows.map((item, index) =>
<MyComponent cell={item} key={index} />
)
CÁCH ĐÚNG : Sử dụng id dữ liệu làm khóa, nó có thể là một số hướng dẫn, v.v.
this.state.rows.map((item) =>
<MyComponent item={item} key={item.id} />
)
vì vậy bằng cách thực hiện cải tiến mã như vậy, thành phần của bạn sẽ DUY NHẤT và hiển thị một cách tự nhiên
Khi bạn muốn hai thành phần React giao tiếp, không bị ràng buộc bởi mối quan hệ (cha-con), bạn nên sử dụng Flux hoặc các kiến trúc tương tự.
Những gì bạn muốn làm là lắng nghe những thay đổi của kho lưu trữ thành phần có thể quan sát , lưu trữ mô hình và giao diện của nó, đồng thời lưu dữ liệu khiến kết xuất thay đổi như state
trong MyComponent
. Khi cửa hàng đẩy dữ liệu mới, bạn thay đổi trạng thái của thành phần, điều này sẽ tự động kích hoạt kết xuất.
Thông thường bạn nên cố gắng tránh sử dụng forceUpdate()
. Từ tài liệu:
Thông thường, bạn nên cố gắng tránh tất cả việc sử dụng forceUpdate () và chỉ đọc từ this.props và this.state trong render (). Điều này làm cho ứng dụng của bạn đơn giản và hiệu quả hơn nhiều
Sử dụng móc hoặc mẫu HOC (thành phần bậc cao hơn) , bạn có thể có các bản cập nhật tự động khi cửa hàng của bạn thay đổi. Đây là một cách tiếp cận rất nhẹ mà không có khuôn khổ.
useStore Hooks cách để xử lý các bản cập nhật cửa hàng
interface ISimpleStore {
on: (ev: string, fn: () => void) => void;
off: (ev: string, fn: () => void) => void;
}
export default function useStore<T extends ISimpleStore>(store: T) {
const [storeState, setStoreState] = useState({store});
useEffect(() => {
const onChange = () => {
setStoreState({store});
}
store.on('change', onChange);
return () => {
store.off('change', onChange);
}
}, []);
return storeState.store;
}
withStores HOC xử lý cập nhật cửa hàng
export default function (...stores: SimpleStore[]) {
return function (WrappedComponent: React.ComponentType<any>) {
return class WithStore extends PureComponent<{}, {lastUpdated: number}> {
constructor(props: React.ComponentProps<any>) {
super(props);
this.state = {
lastUpdated: Date.now(),
};
this.stores = stores;
}
private stores?: SimpleStore[];
private onChange = () => {
this.setState({lastUpdated: Date.now()});
};
componentDidMount = () => {
this.stores &&
this.stores.forEach((store) => {
// each store has a common change event to subscribe to
store.on('change', this.onChange);
});
};
componentWillUnmount = () => {
this.stores &&
this.stores.forEach((store) => {
store.off('change', this.onChange);
});
};
render() {
return (
<WrappedComponent
lastUpdated={this.state.lastUpdated}
{...this.props}
/>
);
}
};
};
}
Lớp SimpleStore
import AsyncStorage from '@react-native-community/async-storage';
import ee, {Emitter} from 'event-emitter';
interface SimpleStoreArgs {
key?: string;
defaultState?: {[key: string]: any};
}
export default class SimpleStore {
constructor({key, defaultState}: SimpleStoreArgs) {
if (key) {
this.key = key;
// hydrate here if you want w/ localState or AsyncStorage
}
if (defaultState) {
this._state = {...defaultState, loaded: false};
} else {
this._state = {loaded: true};
}
}
protected key: string = '';
protected _state: {[key: string]: any} = {};
protected eventEmitter: Emitter = ee({});
public setState(newState: {[key: string]: any}) {
this._state = {...this._state, ...newState};
this.eventEmitter.emit('change');
if (this.key) {
// store on client w/ localState or AsyncStorage
}
}
public get state() {
return this._state;
}
public on(ev: string, fn:() => void) {
this.eventEmitter.on(ev, fn);
}
public off(ev: string, fn:() => void) {
this.eventEmitter.off(ev, fn);
}
public get loaded(): boolean {
return !!this._state.loaded;
}
}
Cách sử dụng
Trong trường hợp móc:
// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';
Trong trường hợp HOC:
// inside your code get/set your store and stuff just updates
const val = myStore.myProp;
myOtherStore.myProp = 'something';
// return your wrapped component like so
export default withStores(myStore)(MyComponent);
ĐẢM BẢO Để xuất các cửa hàng của bạn dưới dạng một cửa hàng riêng lẻ để hưởng lợi từ sự thay đổi toàn cầu như sau:
class MyStore extends SimpleStore {
public get someProp() {
return this._state.someProp || '';
}
public set someProp(value: string) {
this.setState({...this._state, someProp: value});
}
}
// this is a singleton
const myStore = new MyStore();
export {myStore};
Cách tiếp cận này khá đơn giản và phù hợp với tôi. Tôi cũng làm việc trong các nhóm lớn và sử dụng Redux và MobX và nhận thấy những thứ đó cũng tốt nhưng chỉ là quá nhiều bản soạn thảo. Cá nhân tôi chỉ thích cách tiếp cận của riêng tôi bởi vì tôi luôn ghét phải viết nhiều mã cho một thứ gì đó có thể đơn giản khi bạn cần.
Vì vậy, tôi đoán câu hỏi của tôi là: các thành phần React có cần phải có trạng thái để kết xuất không? Có cách nào để buộc thành phần cập nhật theo yêu cầu mà không thay đổi trạng thái không?
Các câu trả lời khác đã cố gắng minh họa cách bạn có thể làm được, nhưng vấn đề là bạn không nên . Ngay cả giải pháp hacky là thay đổi chìa khóa cũng không đúng. Sức mạnh của React là từ bỏ quyền kiểm soát quản lý thủ công khi nào thứ gì đó sẽ hiển thị, và thay vào đó bạn chỉ quan tâm đến cách một thứ gì đó sẽ ánh xạ trên đầu vào. Sau đó, dòng cung cấp các đầu vào.
Nếu bạn cần buộc kết xuất lại theo cách thủ công, gần như chắc chắn bạn đang làm không đúng.
Có một số cách để kết xuất thành phần của bạn:
Giải pháp đơn giản nhất là sử dụng phương thức forceUpdate ():
this.forceUpdate()
Một giải pháp nữa là tạo khóa không sử dụng ở trạng thái (nonUsedKey) và gọi hàm setState với bản cập nhật của nonUsedKey này:
this.setState({ nonUsedKey: Date.now() } );
Hoặc viết lại tất cả trạng thái hiện tại:
this.setState(this.state);
Thay đổi đạo cụ cũng cung cấp kết xuất thành phần.
Bạn có thể làm điều đó theo một số cách:
1. Sử dụng forceUpdate()
phương pháp:
Có một số trục trặc có thể xảy ra khi sử dụng forceUpdate()
phương pháp này. Một ví dụ là nó bỏ qua shouldComponentUpdate()
phương thức và sẽ hiển thị lại chế độ xem bất kể shouldComponentUpdate()
trả về false hay không. Vì điều này nên tránh sử dụng forceUpdate () khi có thể.
2. Chuyển this.state cho setState()
phương thức
Dòng mã sau khắc phục sự cố với ví dụ trước:
this.setState(this.state);
Thực sự tất cả những gì điều này đang làm là ghi đè trạng thái hiện tại bằng trạng thái hiện tại kích hoạt hiển thị lại. Đây vẫn chưa hẳn là cách tốt nhất để thực hiện mọi việc, nhưng nó khắc phục được một số trục trặc mà bạn có thể gặp phải khi sử dụng phương thức forceUpdate ().
Để hoàn thiện, bạn cũng có thể đạt được điều này trong các thành phần chức năng:
const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
// ...
forceUpdate();
Hoặc, như một móc có thể tái sử dụng:
const useForceUpdate = () => {
const [, updateState] = useState();
return useCallback(() => updateState({}), []);
}
// const forceUpdate = useForceUpdate();
Xem: https://stackoverflow.com/a/53215514/2692307
Xin lưu ý rằng việc sử dụng cơ chế buộc cập nhật vẫn là một phương pháp không tốt vì nó đi ngược lại tâm lý phản ứng, vì vậy vẫn nên tránh nếu có thể.
Chúng ta có thể sử dụng this.forceUpdate () như bên dưới.
class MyComponent extends React.Component {
handleButtonClick = ()=>{
this.forceUpdate();
}
render() {
return (
<div>
{Math.random()}
<button onClick={this.handleButtonClick}>
Click me
</button>
</div>
)
}
}
ReactDOM.render(<MyComponent /> , mountNode);
Phần tử 'Math.random' trong DOM chỉ được cập nhật ngay cả khi bạn sử dụng setState để hiển thị lại thành phần.
Tất cả các câu trả lời ở đây là chính xác, bổ sung cho câu hỏi để hiểu..như chúng ta biết để hiển thị lại một thành phần không sử dụng setState ({}) là bằng cách sử dụng forceUpdate ().
Đoạn mã trên chạy với setState như bên dưới.
class MyComponent extends React.Component {
handleButtonClick = ()=>{
this.setState({ });
}
render() {
return (
<div>
{Math.random()}
<button onClick={this.handleButtonClick}>
Click me
</button>
</div>
)
}
}
ReactDOM.render(<MyComponent /> , mountNode);
Chỉ cần một câu trả lời khác để sao lưu câu trả lời được chấp nhận :-)
React không khuyến khích việc sử dụng forceUpdate()
bởi vì chúng thường có cách tiếp cận rất "đây là cách duy nhất để làm việc đó" đối với lập trình hàm. Điều này tốt trong nhiều trường hợp, nhưng nhiều nhà phát triển React có nền tảng OO, và với cách tiếp cận đó, việc lắng nghe một đối tượng có thể quan sát được là điều hoàn toàn phù hợp.
Và nếu bạn làm vậy, bạn có thể biết bạn PHẢI render lại khi các "cháy" có thể quan sát được, và như vậy, bạn NÊN sử dụng forceUpdate()
và đó thực sự là một điểm cộng shouldComponentUpdate()
KHÔNG liên quan ở đây.
Các công cụ như MobX, sử dụng cách tiếp cận OO, thực sự đang thực hiện điều này bên dưới bề mặt (thực sự là MobX gọi render()
trực tiếp)
Tôi thấy tốt nhất là nên tránh forceUpdate (). Một cách để buộc render là thêm phụ thuộc của render () vào một biến bên ngoài tạm thời và thay đổi giá trị của biến đó khi cần thiết.
Đây là một ví dụ về mã:
class Example extends Component{
constructor(props){
this.state = {temp:0};
this.forceChange = this.forceChange.bind(this);
}
forceChange(){
this.setState(prevState => ({
temp: prevState.temp++
}));
}
render(){
return(
<div>{this.state.temp &&
<div>
... add code here ...
</div>}
</div>
)
}
}
Gọi this.forceChange () khi bạn cần buộc kết xuất lại.
ES6 - Tôi bao gồm một ví dụ, rất hữu ích cho tôi:
Trong "câu lệnh if ngắn", bạn có thể chuyển hàm rỗng như sau:
isReady ? ()=>{} : onClick
Đây dường như là cách tiếp cận ngắn nhất.
()=>{}
forceUpdate();
phương pháp sẽ hoạt động nhưng nó được khuyến khích sử dụng setState();
Để hoàn thành những gì bạn đang mô tả, vui lòng thử this.forceUpdate ().
Một cách khác là gọi setState
, trạng thái bảo toàn AND :
this.setState(prevState=>({...prevState}));
forceUpdate (), nhưng mỗi khi tôi đã từng nghe ai đó nói về nó, nó được theo dõi với bạn là đừng bao giờ sử dụng cái này.
Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.
Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?
Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.
Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.
Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?
Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.
Phiên tòa xét xử vụ tấn công tình dục bị trì hoãn nhiều của Harvey Weinstein dự kiến sẽ bắt đầu lựa chọn bồi thẩm đoàn vào tháng 9, và với dự đoán, ông đã sắp xếp lại đội ngũ pháp lý của mình lần thứ ba. Có lẽ không thể tránh khỏi, các luật sư của anh ấy hiện bao gồm luật sư bào chữa Donna Rotunno, người nổi tiếng với việc đại diện cho những người đàn ông bị cáo buộc tấn công tình dục, đặt câu hỏi về phong trào MeToo nói chung và đã nói trong các cuộc phỏng vấn trước đây rằng giới tính của cô ấy cho phép cô ấy thoát khỏi "nọc độc" nhiều hơn khi kiểm tra chéo người tố cáo.
Trong một cuộc phỏng vấn với BBC News, trợ lý cũ của Harvey Weinstein, Zelda Perkins, nói rõ thực tế của việc chống lại ông trùm Hollywood. Cô ấy nói, về cơ bản là không thể.
Nguồn ảnh: AndyKrycek6 Những người hâm mộ No Man's Sky không thể chơi với nhau một cách chính xác, nhưng họ vẫn thích đến với nhau để ăn mừng cộng đồng của họ. Bằng cách nào đó, một kỳ nghỉ mới do người chơi tạo ra đã trở thành một câu chuyện về xung đột, phản bội và sự biến mất của cả một nền văn minh.
Jazmyne Childs đã khóc trong một cuộc họp báo vào ngày 25 tháng 9 năm 2019, khi cô ấy mô tả về hành vi quấy rối tình dục mà cô ấy nói rằng cô ấy đã phải chịu đựng khi làm việc cho phân hội Bắc Carolina của NAACP, ở Raleigh, N.
Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!
Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!
Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không
Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"
Đối với tôi, mọi thứ là về dòng đầu tiên đó và nó sẽ đưa bạn đến đâu. Một số nhà văn bị điều khiển bởi cốt truyện, sự sắp xếp tinh tế của các quân cờ, trong khi những người khác bị lôi cuốn bởi một nhân vật và khả năng thực hiện một cuộc hành trình với một người bạn hư cấu mới.
Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.
Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.
Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.