React.memo crashes app
See original GitHub issueVery specific case, but: React.memo crashes an app if component to memoize is passed as function + some hook used + ViewPropTypes.style used in prop-types validation + some style is passed as props (see “steps to reproduce” for more information).
React Native version: System: OS: macOS Mojave 10.14.6 CPU: (12) x64 Intel® Core™ i7-8700B CPU @ 3.20GHz Memory: 14.36 GB / 32.00 GB Shell: 5.3 - /bin/zsh Binaries: Node: 11.15.0 - /usr/local/bin/node Yarn: 1.17.3 - /usr/local/bin/yarn npm: 6.7.0 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: Android SDK: API Levels: 27, 28 Build Tools: 27.0.3, 28.0.2, 28.0.3 System Images: android-27 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom IDEs: Xcode: /undefined - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.2 => 0.61.2
Steps To Reproduce
- Install latest version of react native via cli (no expo)
- Place the following in app.js:
import React, {memo, useRef} from 'react';
import {Text, View, ViewPropTypes} from 'react-native';
const MyView = memo(({containerStyle}) => {
const someref = useRef();
return (
<View style={containerStyle}>
<Text>some</Text>
</View>
);
});
MyView.propTypes = {
containerStyle: ViewPropTypes.style
};
const App = () => {
return (
<MyView
containerStyle={{
marginTop: 30
}}
/>
);
};
export default App;
- Open application on Android (didn’t tested on iOS) (!!! important !!! issue is not reproducing in debug mode, so if it is enabled - disable it)
- Application will crash after start
Expected behavior
App should not crash
Workarounds
Warning! all this solutions should not be considered as final and good solution, it’s just to provide more information about the bug
Solution 1: as discussed here: /issues/22366 - move "React.memo" to separate line
const MyView = ({containerStyle}) => {
const someref = useRef();
return (
<View style={containerStyle}>
<Text>some</Text>
</View>
);
};
MyView.propTypes = {
containerStyle: ViewPropTypes.style
};
const MemoizedMyView = memo(MyView);
const App = () => {
return (
<MemoizedMyView
containerStyle={{
marginTop: 30
}}
/>
);
};
export default App;
Solution 2: remove any hooks used inside memoized component
const MyView = memo(({containerStyle}) => {
// after we remove any hooks from component - app will render properly:
// const someref = useRef();
return (
<View style={containerStyle}>
<Text>some</Text>
</View>
);
});
MyView.propTypes = {
containerStyle: ViewPropTypes.style
};
const App = () => {
return (
<MyView
containerStyle={{
marginTop: 30
}}
/>
);
};
export default App;
Solution 3: do not pass styles in props of rendered component
const MyView = memo(({containerStyle}) => {
const someref = useRef();
return (
<View style={containerStyle}>
<Text>some</Text>
</View>
);
});
MyView.propTypes = {
containerStyle: ViewPropTypes.style
};
const App = () => {
return (
<MyView
// Just remove styles - and all will work fine:
// containerStyle={{
// marginTop: 30
// }}
/>
);
};
export default App;
Solution 4: remove styles validation from prop types
const MyView = memo(({containerStyle}) => {
const someref = useRef();
return (
<View style={containerStyle}>
<Text>some</Text>
</View>
);
});
MyView.propTypes = {
// If we remove styles validation - all will work fine:
// containerStyle: ViewPropTypes.style
};
const App = () => {
return (
<MyView
containerStyle={{
marginTop: 30
}}
/>
);
};
export default App;
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (1 by maintainers)
Top GitHub Comments
I can confirm this is an issue on react 16.8.3 and react-native 0.59.10.
@retyui Tested with react 16.9.0 - bug is still reproducing. Updated “React Native version” section.