mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-06-15 03:28:50 +08:00
Summary: In React Native there are several use cases where React State is not the only input that affects the component tree. E.g., in case of a <Modal> component, the screen size directly affects the layout of components inside modal; in the case of uncontrolled <TextInput> component, the text inside the input affects the layout of the surrounding components. `State` is a special (legit!) workaround for all those similar cases. Native part of React Native maintains a special shared object between all nodes of the same family and use that during cloning and commits. See coming commits to know how to use that. In the near future State will fully replace LocalData concept but for simplicity they both exist for now. Reviewed By: mdvacca Differential Revision: D14217184 fbshipit-source-id: 6e018c5b68208d662462013bce0f4e2733d2f673
105 lines
2.8 KiB
C++
105 lines
2.8 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.
|
|
*/
|
|
|
|
#include "EventEmitter.h"
|
|
|
|
#include <folly/dynamic.h>
|
|
#include <jsi/JSIDynamic.h>
|
|
#include <jsi/jsi.h>
|
|
#include <react/debug/SystraceSection.h>
|
|
|
|
#include "RawEvent.h"
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
// TODO(T29874519): Get rid of "top" prefix once and for all.
|
|
/*
|
|
* Capitalizes the first letter of the event type and adds "top" prefix if
|
|
* necessary (e.g. "layout" becames "topLayout").
|
|
*/
|
|
static std::string normalizeEventType(const std::string &type) {
|
|
auto prefixedType = type;
|
|
if (type.find("top", 0) != 0) {
|
|
prefixedType.insert(0, "top");
|
|
prefixedType[3] = toupper(prefixedType[3]);
|
|
}
|
|
return prefixedType;
|
|
}
|
|
|
|
std::mutex &EventEmitter::DispatchMutex() {
|
|
static std::mutex mutex;
|
|
return mutex;
|
|
}
|
|
|
|
ValueFactory EventEmitter::defaultPayloadFactory() {
|
|
static auto payloadFactory =
|
|
ValueFactory{[](jsi::Runtime &runtime) { return jsi::Object(runtime); }};
|
|
return payloadFactory;
|
|
}
|
|
|
|
EventEmitter::EventEmitter(
|
|
SharedEventTarget eventTarget,
|
|
Tag tag,
|
|
EventDispatcher::Weak eventDispatcher)
|
|
: eventTarget_(std::move(eventTarget)),
|
|
eventDispatcher_(std::move(eventDispatcher)) {}
|
|
|
|
void EventEmitter::dispatchEvent(
|
|
const std::string &type,
|
|
const folly::dynamic &payload,
|
|
const EventPriority &priority) const {
|
|
dispatchEvent(
|
|
type,
|
|
[payload](jsi::Runtime &runtime) {
|
|
return valueFromDynamic(runtime, payload);
|
|
},
|
|
priority);
|
|
}
|
|
|
|
void EventEmitter::dispatchEvent(
|
|
const std::string &type,
|
|
const ValueFactory &payloadFactory,
|
|
const EventPriority &priority) const {
|
|
SystraceSection s("EventEmitter::dispatchEvent");
|
|
|
|
auto eventDispatcher = eventDispatcher_.lock();
|
|
if (!eventDispatcher) {
|
|
return;
|
|
}
|
|
|
|
eventDispatcher->dispatchEvent(
|
|
RawEvent(normalizeEventType(type), payloadFactory, eventTarget_),
|
|
priority);
|
|
}
|
|
|
|
void EventEmitter::setEnabled(bool enabled) const {
|
|
enableCounter_ += enabled ? 1 : -1;
|
|
|
|
bool shouldBeEnabled = enableCounter_ > 0;
|
|
if (isEnabled_ != shouldBeEnabled) {
|
|
isEnabled_ = shouldBeEnabled;
|
|
if (eventTarget_) {
|
|
eventTarget_->setEnabled(isEnabled_);
|
|
}
|
|
}
|
|
|
|
// Note: Initially, the state of `eventTarget_` and the value `enableCounter_`
|
|
// is mismatched intentionally (it's `non-null` and `0` accordingly). We need
|
|
// this to support an initial nebula state where the event target must be
|
|
// retained without any associated mounted node.
|
|
bool shouldBeRetained = enableCounter_ > 0;
|
|
if (shouldBeRetained != (eventTarget_ != nullptr)) {
|
|
if (!shouldBeRetained) {
|
|
eventTarget_.reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|