mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Initialise ScrollView state with content offset from props (#36961)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36961 changelog: [internal] Initial state must reflect content offset, otherwise ShadowTree will not know about the contentOffset until user scrolls. This was affecting both, iOS and Android. Reviewed By: mdvacca Differential Revision: D45087358 fbshipit-source-id: 8812c2d3fe97e017938a9a81acbb31d579a00d45
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6971540c90
commit
2d9c81780c
+13
@@ -48,6 +48,19 @@ void ScrollViewShadowNode::updateScrollContentOffsetIfNeeded() {
|
||||
#endif
|
||||
}
|
||||
|
||||
ScrollViewState ScrollViewShadowNode::initialStateData(
|
||||
const ShadowNodeFragment &fragment,
|
||||
const ShadowNodeFamilyFragment & /*familyFragment*/,
|
||||
const ComponentDescriptor & /*componentDescriptor*/) {
|
||||
if (fragment.props != ShadowNodeFragment::propsPlaceholder()) {
|
||||
auto const &scrollViewProps =
|
||||
static_cast<ScrollViewProps const &>(*fragment.props);
|
||||
return {scrollViewProps.contentOffset, {}, 0};
|
||||
} else {
|
||||
return ScrollViewState{};
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void ScrollViewShadowNode::layout(LayoutContext layoutContext) {
|
||||
|
||||
+5
@@ -28,6 +28,11 @@ class ScrollViewShadowNode final : public ConcreteViewShadowNode<
|
||||
public:
|
||||
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
||||
|
||||
static ScrollViewState initialStateData(
|
||||
ShadowNodeFragment const &fragment,
|
||||
ShadowNodeFamilyFragment const &familyFragment,
|
||||
ComponentDescriptor const &componentDescriptor);
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void layout(LayoutContext layoutContext) override;
|
||||
|
||||
+8
@@ -9,6 +9,14 @@
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
ScrollViewState::ScrollViewState(
|
||||
Point contentOffset,
|
||||
Rect contentBoundingRect,
|
||||
int scrollAwayPaddingTop)
|
||||
: contentOffset(contentOffset),
|
||||
contentBoundingRect(contentBoundingRect),
|
||||
scrollAwayPaddingTop(scrollAwayPaddingTop) {}
|
||||
|
||||
Size ScrollViewState::getContentSize() const {
|
||||
return contentBoundingRect.size;
|
||||
}
|
||||
|
||||
+6
-1
@@ -25,6 +25,12 @@ namespace facebook::react {
|
||||
*/
|
||||
class ScrollViewState final {
|
||||
public:
|
||||
ScrollViewState(
|
||||
Point contentOffset,
|
||||
Rect contentBoundingRect,
|
||||
int scrollAwayPaddingTop);
|
||||
ScrollViewState() = default;
|
||||
|
||||
Point contentOffset;
|
||||
Rect contentBoundingRect;
|
||||
int scrollAwayPaddingTop;
|
||||
@@ -35,7 +41,6 @@ class ScrollViewState final {
|
||||
Size getContentSize() const;
|
||||
|
||||
#ifdef ANDROID
|
||||
ScrollViewState() = default;
|
||||
ScrollViewState(ScrollViewState const &previousState, folly::dynamic data)
|
||||
: contentOffset(
|
||||
{(Float)data["contentOffsetLeft"].getDouble(),
|
||||
|
||||
@@ -31,19 +31,19 @@ ShadowNode::Unshared ComponentBuilder::build(
|
||||
elementFragment.tag, elementFragment.surfaceId, nullptr},
|
||||
nullptr);
|
||||
|
||||
auto state = componentDescriptor.createInitialState(
|
||||
auto initialState = componentDescriptor.createInitialState(
|
||||
ShadowNodeFragment{elementFragment.props}, family);
|
||||
|
||||
auto constShadowNode = componentDescriptor.createShadowNode(
|
||||
ShadowNodeFragment{
|
||||
elementFragment.props,
|
||||
std::make_shared<ShadowNode::ListOfShared const>(children),
|
||||
state},
|
||||
initialState},
|
||||
family);
|
||||
|
||||
if (elementFragment.stateCallback) {
|
||||
auto newState = componentDescriptor.createState(
|
||||
*family, elementFragment.stateCallback());
|
||||
*family, elementFragment.stateCallback(initialState));
|
||||
constShadowNode = componentDescriptor.cloneShadowNode(
|
||||
*constShadowNode,
|
||||
ShadowNodeFragment{
|
||||
|
||||
@@ -92,9 +92,11 @@ class Element final {
|
||||
* Sets `state` using callback.
|
||||
*/
|
||||
Element &stateData(std::function<void(ConcreteStateData &)> callback) {
|
||||
fragment_.stateCallback = [callback =
|
||||
std::move(callback)]() -> StateData::Shared {
|
||||
auto stateData = ConcreteStateData();
|
||||
fragment_.stateCallback =
|
||||
[callback = std::move(callback)](
|
||||
State::Shared const &state) -> StateData::Shared {
|
||||
auto stateData =
|
||||
static_cast<ConcreteState const *>(state.get())->getData();
|
||||
callback(stateData);
|
||||
return std::make_shared<ConcreteStateData>(stateData);
|
||||
};
|
||||
|
||||
@@ -29,7 +29,8 @@ class ElementFragment final {
|
||||
using ReferenceCallback =
|
||||
std::function<void(ShadowNode::Unshared const &shadowNode)>;
|
||||
using FinalizeCallback = std::function<void(ShadowNode &shadowNode)>;
|
||||
using StateCallback = std::function<StateData::Shared()>;
|
||||
using StateCallback =
|
||||
std::function<StateData::Shared(State::Shared const &state)>;
|
||||
|
||||
/*
|
||||
* ComponentDescriptor part (describes the type)
|
||||
|
||||
Reference in New Issue
Block a user