Files
react-native/ReactCommon/fabric/components/textinput/androidtextinput/AndroidTextInputShadowNode.h
T
Joshua Gross e689462782 AndroidTextInput: Fix stale measurements based on outdated State
Summary:
Fix initial width measurement of AndroidTextInput.

The lifecycle here between measure and layout is a little wacky. I put this in comments too, but:

1. Measure is called first. It's marked as const so it can't call updateStateIfNeeded.
2. Layout is called immediately after. It's not const so it calls updateStateIfNeeded.
3. The state is updated, but it's not part of a commit, it just mutates the node in-place.
4. If the node isn't dirtied again, measure won't be called again.

For completeness: I did try calling `dirtyLayout` in the `layout` method. That does not work.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D19549803

fbshipit-source-id: f3798e10dca2edacb364cc5b53f58f091de5e4d0
2020-01-23 19:27:57 -08:00

80 lines
2.3 KiB
C++

/*
* 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.
*/
#pragma once
#include "AndroidTextInputEventEmitter.h"
#include "AndroidTextInputProps.h"
#include "AndroidTextInputState.h"
#include <react/components/view/ConcreteViewShadowNode.h>
#include <react/utils/ContextContainer.h>
#include <react/attributedstring/AttributedString.h>
namespace facebook {
namespace react {
extern const char AndroidTextInputComponentName[];
/*
* `ShadowNode` for <AndroidTextInput> component.
*/
class AndroidTextInputShadowNode : public ConcreteViewShadowNode<
AndroidTextInputComponentName,
AndroidTextInputProps,
AndroidTextInputEventEmitter,
AndroidTextInputState> {
public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;
void setContextContainer(ContextContainer *contextContainer);
/*
* Returns a `AttributedString` which represents text content of the node.
*/
AttributedString getAttributedString() const;
AttributedString getPlaceholderAttributedString() const;
/*
* Associates a shared TextLayoutManager with the node.
* `ParagraphShadowNode` uses the manager to measure text content
* and construct `ParagraphState` objects.
*/
void setTextLayoutManager(SharedTextLayoutManager textLayoutManager);
#pragma mark - LayoutableShadowNode
Size measure(LayoutConstraints layoutConstraints) const override;
void layout(LayoutContext layoutContext) override;
private:
ContextContainer *contextContainer_{};
/**
* Get the most up-to-date attributed string for measurement and State.
*/
AttributedString getMostRecentAttributedString() const;
/*
* Creates a `State` object (with `AttributedText` and
* `TextLayoutManager`) if needed.
*/
void updateStateIfNeeded();
SharedTextLayoutManager textLayoutManager_;
/*
* Cached attributed string that represents the content of the subtree started
* from the node.
*/
mutable folly::Optional<AttributedString> cachedAttributedString_{};
};
} // namespace react
} // namespace facebook