diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index a077f7b97f8d19..b347c29db7384a 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -607,12 +607,11 @@ const ScrollResponderMixin = { }, /** - * `componentWillMount` is the closest thing to a standard "constructor" for - * React components. + * Constructor for this mixin, call from constructor or from deprecated UNSAFE_componentWillMount * * The `keyboardWillShow` is called before input focus. */ - UNSAFE_componentWillMount: function() { + scrollResponderMixinConstructor: function() { const {keyboardShouldPersistTaps} = this.props; warning( typeof keyboardShouldPersistTaps !== 'boolean', diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index e0c0a7a5faea6b..5b96043a9c5f19 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -636,6 +636,17 @@ class ScrollView extends React.Component { // $FlowFixMe - dynamically adding properties to a class (this: any)[key] = ScrollResponder.Mixin[key]; }); + + this._scrollResponder.scrollResponderMixinConstructor(); + + this._scrollAnimatedValue = new AnimatedImplementation.Value( + props.contentOffset ? props.contentOffset.y : 0, + ); + this._scrollAnimatedValue.setOffset( + props.contentInset ? props.contentInset.top : 0, + ); + this._stickyHeaderRefs = new Map(); + this._headerLayoutYs = new Map(); } _scrollAnimatedValue: AnimatedImplementation.Value = new AnimatedImplementation.Value( @@ -650,35 +661,21 @@ class ScrollView extends React.Component { ...ScrollResponder.Mixin.scrollResponderMixinGetInitialState(), }; - UNSAFE_componentWillMount() { - this._scrollResponder.UNSAFE_componentWillMount(); - this._scrollAnimatedValue = new AnimatedImplementation.Value( - this.props.contentOffset ? this.props.contentOffset.y : 0, - ); - this._scrollAnimatedValue.setOffset( - this.props.contentInset ? this.props.contentInset.top : 0, - ); - this._stickyHeaderRefs = new Map(); - this._headerLayoutYs = new Map(); + componentDidMount() { + this._updateAnimatedNodeAttachment(); } - UNSAFE_componentWillReceiveProps(nextProps: Props) { + componentDidUpdate(prevProps: Props) { + const prevContentInsetTop = prevProps.contentInset + ? prevProps.contentInset.top + : 0; const currentContentInsetTop = this.props.contentInset ? this.props.contentInset.top : 0; - const nextContentInsetTop = nextProps.contentInset - ? nextProps.contentInset.top - : 0; - if (currentContentInsetTop !== nextContentInsetTop) { - this._scrollAnimatedValue.setOffset(nextContentInsetTop || 0); + if (prevContentInsetTop !== currentContentInsetTop) { + this._scrollAnimatedValue.setOffset(currentContentInsetTop || 0); } - } - - componentDidMount() { - this._updateAnimatedNodeAttachment(); - } - componentDidUpdate() { this._updateAnimatedNodeAttachment(); } diff --git a/RNTester/js/RNTesterList.android.js b/RNTester/js/RNTesterList.android.js index d4bf68db97d46d..eed509e656f296 100644 --- a/RNTester/js/RNTesterList.android.js +++ b/RNTester/js/RNTesterList.android.js @@ -222,6 +222,10 @@ const APIExamples: Array = [ key: 'ShareExample', module: require('./ShareExample'), }, + { + key: 'StrictModeExample', + module: require('./StrictModeExample'), + }, { key: 'TimePickerAndroidExample', module: require('./TimePickerAndroidExample'), diff --git a/RNTester/js/RNTesterList.ios.js b/RNTester/js/RNTesterList.ios.js index c5d6c2b0122f94..65a1351d9f1ad3 100644 --- a/RNTester/js/RNTesterList.ios.js +++ b/RNTester/js/RNTesterList.ios.js @@ -316,6 +316,10 @@ const APIExamples: Array = [ module: require('./SnapshotExample'), supportsTVOS: true, }, + { + key: 'StrictModeExample', + module: require('./StrictModeExample'), + }, { key: 'TimerExample', module: require('./TimerExample'), diff --git a/RNTester/js/StrictModeExample.js b/RNTester/js/StrictModeExample.js new file mode 100644 index 00000000000000..1ca3964d76c263 --- /dev/null +++ b/RNTester/js/StrictModeExample.js @@ -0,0 +1,47 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +const React = require('react'); +const {StrictMode} = React; +const ReactNative = require('react-native'); +const {ScrollView, Text} = ReactNative; + +type Props = $ReadOnly<{||}>; +type State = {|result: string|}; + +const componentsToTest = [ScrollView]; + +class StrictModeExample extends React.Component { + render() { + return ( + + {componentsToTest.map(Component => ( + + {Component.displayName} + + ))} + + ); + } +} + +exports.framework = 'React'; +exports.title = 'StrictMode'; +exports.description = 'See components in strict mode.'; +exports.examples = [ + { + title: 'Strict Mode', + render() { + return ; + }, + }, +];