Skip to content

Commit 8538ebf

Browse files
Return null to opt-out from re-rendering when handling non state changing effects
1 parent 1b74cc8 commit 8538ebf

File tree

2 files changed

+60
-21
lines changed

2 files changed

+60
-21
lines changed

__tests__/UpdateTypes-test.js

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ describe("UpdateTypes", () => {
1919
sideEffects,
2020
updateWithSideEffects,
2121
invalid,
22-
unhandled;
22+
unhandled,
23+
numberOfRenders;
2324
beforeEach(() => {
2425
container = document.createElement("div");
2526
document.body.appendChild(container);
27+
numberOfRenders = 0;
2628
sideEffectSpy = jest.fn();
2729
});
2830

@@ -58,6 +60,9 @@ describe("UpdateTypes", () => {
5860
}
5961

6062
render() {
63+
// We use this to assert that certain effects do not re-render the state.
64+
numberOfRenders++;
65+
6166
return (
6267
<React.Fragment>
6368
You’ve clicked {this.state.count} times(s)
@@ -66,32 +71,64 @@ describe("UpdateTypes", () => {
6671
}
6772
}
6873

69-
it("NoUpdate", () => {
70-
const instance = ReactDOM.render(<ReducerReturns />, container);
71-
noUpdate();
72-
expect(container.textContent).toEqual("You’ve clicked 0 times(s)");
73-
expect(sideEffectSpy).not.toHaveBeenCalled();
74+
describe("NoUpdate", () => {
75+
it("does not update the state", () => {
76+
const instance = ReactDOM.render(<ReducerReturns />, container);
77+
noUpdate();
78+
expect(container.textContent).toEqual("You’ve clicked 0 times(s)");
79+
expect(sideEffectSpy).not.toHaveBeenCalled();
80+
});
81+
82+
it("does not re-render", () => {
83+
const instance = ReactDOM.render(<ReducerReturns />, container);
84+
noUpdate();
85+
expect(numberOfRenders).toEqual(1);
86+
});
7487
});
7588

76-
it("Update", () => {
77-
const instance = ReactDOM.render(<ReducerReturns />, container);
78-
update();
79-
expect(container.textContent).toEqual("You’ve clicked 1 times(s)");
80-
expect(sideEffectSpy).not.toHaveBeenCalled();
89+
describe("Update", () => {
90+
it("updates the state", () => {
91+
const instance = ReactDOM.render(<ReducerReturns />, container);
92+
update();
93+
expect(container.textContent).toEqual("You’ve clicked 1 times(s)");
94+
expect(sideEffectSpy).not.toHaveBeenCalled();
95+
});
96+
97+
it("re-renders", () => {
98+
const instance = ReactDOM.render(<ReducerReturns />, container);
99+
update();
100+
expect(numberOfRenders).toEqual(2);
101+
});
81102
});
82103

83-
it("SideEffects", () => {
84-
const instance = ReactDOM.render(<ReducerReturns />, container);
85-
sideEffects();
86-
expect(container.textContent).toEqual("You’ve clicked 0 times(s)");
87-
expect(sideEffectSpy).toHaveBeenCalled();
104+
describe("SideEffects", () => {
105+
it("does not update the state but triggers the side effect", () => {
106+
const instance = ReactDOM.render(<ReducerReturns />, container);
107+
sideEffects();
108+
expect(container.textContent).toEqual("You’ve clicked 0 times(s)");
109+
expect(sideEffectSpy).toHaveBeenCalled();
110+
});
111+
112+
it("does not re-render", () => {
113+
const instance = ReactDOM.render(<ReducerReturns />, container);
114+
sideEffects();
115+
expect(numberOfRenders).toEqual(1);
116+
});
88117
});
89118

90-
it("UpdateWithSideEffects", () => {
91-
const instance = ReactDOM.render(<ReducerReturns />, container);
92-
updateWithSideEffects();
93-
expect(container.textContent).toEqual("You’ve clicked 1 times(s)");
94-
expect(sideEffectSpy).toHaveBeenCalled();
119+
describe("UpdateWithSideEffects", () => {
120+
it("updates the state and triggers the side effect", () => {
121+
const instance = ReactDOM.render(<ReducerReturns />, container);
122+
updateWithSideEffects();
123+
expect(container.textContent).toEqual("You’ve clicked 1 times(s)");
124+
expect(sideEffectSpy).toHaveBeenCalled();
125+
});
126+
127+
it("re-renders", () => {
128+
const instance = ReactDOM.render(<ReducerReturns />, container);
129+
updateWithSideEffects();
130+
expect(numberOfRenders).toEqual(2);
131+
});
95132
});
96133

97134
it("throws when an invalid value was returned", () => {

src/re.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,13 @@ export function Re(Component) {
9999

100100
switch (reduced.type) {
101101
case NO_UPDATE:
102+
state = null;
102103
break;
103104
case UPDATE:
104105
state = reduced.state;
105106
break;
106107
case SIDE_EFFECTS:
108+
state = null;
107109
sideEffects = reduced.sideEffects;
108110
break;
109111
case UPDATE_WITH_SIDE_EFFECTS:

0 commit comments

Comments
 (0)