• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

infernojs / inferno / 6333

pending completion
6333

push

travis-ci

Ryan Megidov
Added MobX "useStaticRendering" method and additional tests

1928 of 2428 branches covered (79.41%)

138 of 138 new or added lines in 5 files covered. (100.0%)

2887 of 3279 relevant lines covered (88.05%)

1889.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.76
/packages/inferno-mobx/src/makeReactive.ts
1
/**
2
 * @module Inferno-Mobx
3
 */ /** TypeDoc Comment */
4

5
import Component from "inferno-component";
6
import { throwError, warning } from "inferno-shared";
7
import { extras, isObservable, Reaction } from "mobx";
8
import EventEmitter from "./utils/EventEmitter";
9

10
/**
11
 * Dev tools support
5✔
12
 */
5✔
13
let isDevtoolsEnabled = false;
5✔
14

5✔
15
let isUsingStaticRendering = false;
16

×
17
export const componentByNodeRegistery: WeakMap<any, any> = new WeakMap();
×
18
export const renderReporter = new EventEmitter();
×
19

20
function reportRendering(component) {
×
21
  const node = component._vNode.dom;
22
  if (node && componentByNodeRegistery) {
23
    componentByNodeRegistery.set(node, component);
24
  }
25

26
  renderReporter.emit({
27
    component,
28
    event: "render",
29
    node,
×
30
    renderTime: component.__$mobRenderEnd - component.__$mobRenderStart,
×
31
    totalTime: Date.now() - component.__$mobRenderStart
32
  });
×
33
}
×
34

35
export function trackComponents() {
36
  if (typeof WeakMap === "undefined") {
37
    throwError(
×
38
      "[inferno-mobx] tracking components is not supported in this browser."
39
    );
40
  }
10!
41
  if (!isDevtoolsEnabled) {
×
42
    isDevtoolsEnabled = true;
43
  }
44
}
10!
45

×
46
export function useStaticRendering(boolean) {
47
  isUsingStaticRendering = boolean;
48
}
10✔
49

10✔
50
interface IReactiveRender {
1✔
51
  $mobx?: Reaction;
52
  (nextProps, nextContext): void;
9✔
53
}
6✔
54

6✔
55
function scuMobx(nextProps, nextState) {
6✔
56
  if (isUsingStaticRendering) {
2✔
57
    warning(
58
      "[inferno-mobx] It seems that a re-rendering of a React component is triggered while in static (server-side) mode. Please make sure components are rendered only once server-side."
4✔
59
    );
60
  }
61

62
  // Update on any state changes (as is the default)
63
  if (this.state !== nextState) {
2✔
64
    return true;
65
  }
66

5✔
67
  // Update if props are shallowly not equal, inspired by PureRenderMixin
68
  const keys = Object.keys(this.props);
69
  if (keys.length !== Object.keys(nextProps).length) {
25!
70
    return true;
25✔
71
  }
25✔
72

25✔
73
  for (let i = keys.length - 1; i >= 0; i--) {
25✔
74
    const key = keys[i];
25!
75
    const newValue = nextProps[key];
×
76
    if (newValue !== this.props[key]) {
77
      return true;
78
    } else if (
25!
79
      newValue &&
×
80
      typeof newValue === "object" &&
81
      !isObservable(newValue)
82
    ) {
25✔
83
      // If the newValue is still the same object, but that object is not observable,
25✔
84
      // fallback to the default behavior: update, because the object *might* have changed.
85
      return true;
86
    }
87
  }
88
  return false;
25✔
89
}
25✔
90

25✔
91
export default function makeReactive(componentClass) {
3!
92
  const target = componentClass.prototype || componentClass;
3✔
93
  const baseDidMount = target.componentDidMount;
3!
94
  const baseWillMount = target.componentWillMount;
3✔
95
  const baseUnmount = target.componentWillUnmount;
3✔
96

3✔
97
  target.componentWillMount = function() {
3✔
98
    if (isUsingStaticRendering === true) {
99
      return;
100
    }
3!
101

×
102
    // Call original
103
    if (baseWillMount) {
104
      baseWillMount.call(this);
105
    }
106

107
    let reaction: Reaction;
25✔
108
    let isRenderingPending = false;
25✔
109

25✔
110
    const initialName =
111
      this.displayName ||
25✔
112
      this.name ||
30✔
113
      (this.constructor &&
114
        (this.constructor.displayName || this.constructor.name)) ||
30✔
115
      "<component>";
30!
116
    const baseRender = this.render.bind(this);
×
117

118
    const initialRender = (nextProps, nextContext) => {
30✔
119
      reaction = new Reaction(`${initialName}.render()`, () => {
30!
120
        if (!isRenderingPending) {
×
121
          isRenderingPending = true;
122
          if (this.__$mobxIsUnmounted !== true) {
123
            let hasError = true;
30✔
124
            try {
125
              Component.prototype.forceUpdate.call(this);
25✔
126
              hasError = false;
127
            } finally {
25✔
128
              if (hasError) {
25!
129
                reaction.dispose();
×
130
              }
131
            }
132
          }
25!
133
        }
×
134
      });
135
      reactiveRender.$mobx = reaction;
136
      this.render = reactiveRender;
25✔
137
      return reactiveRender(nextProps, nextContext);
25!
138
    };
×
139

140
    const reactiveRender: IReactiveRender = (nextProps, nextContext) => {
141
      isRenderingPending = false;
25!
142
      let rendering;
×
143
      reaction.track(() => {
144
        if (isDevtoolsEnabled) {
145
          this.__$mobRenderStart = Date.now();
25!
146
        }
25✔
147
        rendering = extras.allowStateChanges(
148
          false,
25✔
149
          baseRender.bind(this, nextProps, nextContext)
25!
150
        );
×
151
        if (isDevtoolsEnabled) {
×
152
          this.__$mobRenderEnd = Date.now();
×
153
        }
154
      });
×
155
      return rendering;
156
    };
157

158
    this.render = initialRender;
159
  };
160

161
  target.componentDidMount = function() {
25✔
162
    if (isDevtoolsEnabled) {
24✔
163
      reportRendering(this);
164
    }
25✔
165

166
    // Call original
167
    if (baseDidMount) {
168
      baseDidMount.call(this);
169
    }
170
  };
171

172
  target.componentWillUnmount = function() {
173
    if (isUsingStaticRendering === true) {
174
      return;
175
    }
176

177
    // Call original
178
    if (baseUnmount) {
179
      baseUnmount.call(this);
180
    }
181

182
    // Dispose observables
183
    if (this.render.$mobx) {
184
      this.render.$mobx.dispose();
185
    }
186
    this.__$mobxIsUnmounted = true;
187

188
    if (isDevtoolsEnabled) {
189
      const node = this._vNode.dom;
190
      if (node && componentByNodeRegistery) {
191
        componentByNodeRegistery.delete(node);
192
      }
193
      renderReporter.emit({
194
        component: this,
195
        event: "destroy",
196
        node
197
      });
198
    }
199
  };
200

201
  if (!target.shouldComponentUpdate) {
202
    target.shouldComponentUpdate = scuMobx;
203
  }
204

205
  return componentClass;
206
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc