diff --git a/.spelling b/.spelling index 604e8e071..be2abe9d9 100644 --- a/.spelling +++ b/.spelling @@ -46,7 +46,9 @@ initializer interop iOS ItemGroup +JSValue KeyEvents +Kotlin lifecycle macOS middleware @@ -80,6 +82,7 @@ Quickstart react-native react-native-macos react-native-windows +reactnative.dev RefreshControl repo repos @@ -96,6 +99,7 @@ struct symlink symlinks tada +testlib TextInput theming toolchain diff --git a/docs/autolink-windows-cli.md b/docs/autolink-windows-cli.md index 6f942f328..727883371 100644 --- a/docs/autolink-windows-cli.md +++ b/docs/autolink-windows-cli.md @@ -31,7 +31,9 @@ Here are the options that `react-native autolink-windows` takes: | `--no-telemetry` | boolean | Disables sending telemetry that allows analysis of usage and failures of the react-native-windows CLI | | `-h`, `--help` | boolean | Display help for command | -This sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. +## Telemetry Notice + +This command sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/docs/codegen-windows-cli.md b/docs/codegen-windows-cli.md index 267147dc5..449d5e3d8 100644 --- a/docs/codegen-windows-cli.md +++ b/docs/codegen-windows-cli.md @@ -27,7 +27,51 @@ Here are the options that `react-native codegen-windows` takes: | `--no-telemetry` | boolean | Disables sending telemetry that allows analysis of usage and failures of the react-native-windows CLI | | `-h`, `--help` | boolean | Display help for command | -This sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. +## Codegen Config + +The `react-native codegen-windows` command is configured by the `codegenConfig` object in the project's `package.json` file. This `codegenConfig` object is shared by all platforms, but the relevant parts for React Native for Windows is configured as follows: + +| Field | Type| Description | +|:------|:---:|:------------| +| `type` | string | `"modules"` for Native Modules, `"components"` for Native Components, or `"all"` for both | +| `jsSrcDir` | string | Path to the TypeScript spec input files | +| `windows` | object | Windows-specific codegen configuration | + +The `windows` object is configured as follows: + +| Field | Type| Description | +|:------|:---:|:------------| +| `namespace` | string | The C++ namespace to contain the generated code | +| `cppStringType` | string | Optional, the string type to use in C++ code, either `"std::string"` or `std::wstring`. Defaults to `"std::string"` | +| `generators` | array | Optional, array of codegen generator strings, accepting `"modulesWindows"` for Native Modules, `"componentsWindows"` for Native Components. Defaults to `[ "modulesWindows" ]` | +| `outputDirectory` | string | Optional, path to place the generated code. Defaults to `./codegen/` of the working directory | +| `separateDataTypes` | boolean | Optional, specify whether to create separate files to define custom data types. Defaults to `false` | + +> **Note:** For more information on how to configure the `codegenConfig` object for other platforms, see the [reactnative.dev Configuring Codegen](https://reactnative.dev/docs/the-new-architecture/using-codegen#configuring-codegen) page. + +### Example Codegen Config + +```json +"codegenConfig": { + "name": "NativeModuleSampleSpec", + "type": "all", + "jsSrcsDir": "src", + "includesGeneratedCode": true, + "windows": { + "namespace": "NativeModuleSampleCodegen", + "generators": [ + "modulesWindows", + "componentsWindows" + ], + "outputDirectory": "windows/NativeModuleSample/codegen", + "separateDataTypes": true + } + }, +``` + +## Telemetry Notice + +This command sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/docs/getting-started.md b/docs/getting-started.md index 389c240d7..95adbd353 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -15,13 +15,12 @@ For information around how to set up React Native, see the [React Native Getting ## Create a new React Native project -Remember to call `@react-native-community/cli init` from the place you want your project directory to live. +Call the following from the place where you want your project directory to live: - - + @@ -119,7 +118,7 @@ npx react-native init-windows --overwrite ## Authoring Native Modules -See [Native Modules and React Native Windows](native-modules.md). +See [Native Platform: Overview](native-platform.md). ## Building a standalone React Native Windows App diff --git a/docs/init-windows-cli.md b/docs/init-windows-cli.md index ef8221b45..fbd4bc03d 100644 --- a/docs/init-windows-cli.md +++ b/docs/init-windows-cli.md @@ -30,20 +30,20 @@ Here are the options that `react-native init-windows` takes: | `--no-telemetry` | boolean | Disables sending telemetry that allows analysis of usage and failures of the react-native-windows CLI | | `-h`, `--help` | boolean | Display help for command | -### Templates +## Templates The following templates are available for use with `init-windows` by replacing `--template XYZ`, where `XYZ` can be: | Template | Name | |:-:|:--| -| `cpp-app` | React Native Windows Application (New Arch, C++, Win32, Hermes) | -| `cpp-lib` | React Native Windows Turbo Module (New Arch, C++) | +| `cpp-app` | React Native Windows Application (New Arch, WinAppSDK, C++) | +| `cpp-lib` | React Native Windows Library (C++) | | `old/uwp-cpp-app` | React Native Windows Application (Old Arch, UWP, C++) | -| `old/uwp-cpp-lib` | React Native Windows Library (Old Arch, UWP, C++) | | `old/uwp-cs-app` | React Native Windows Application (Old Arch, UWP, C#) | -| `old/uwp-cs-lib` | React Native Windows Library (Old Arch, UWP, C#) | -This sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. +## Telemetry Notice + +This command sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/docs/native-code-language-choice.md b/docs/native-code-language-choice.md index 8b40a2284..9e8f06f24 100644 --- a/docs/native-code-language-choice.md +++ b/docs/native-code-language-choice.md @@ -7,9 +7,11 @@ title: Choosing C++ or C# for native code > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + React Native for Windows supports writing native code in both C++ and C#, but there are trade-offs with each language. The choice of language can impact the compatibility, developer experience, and performance of your project. So whether you're building an app or native module, you should choose the native language that best meets your requirements. -> **Note**: In this document, C++ refers specifically to C++/WinRT. +> **Note:** In this document, C++ refers specifically to C++/WinRT. ## Common Considerations diff --git a/docs/native-code.md b/docs/native-code.md index d801f2b31..238cc6b4d 100644 --- a/docs/native-code.md +++ b/docs/native-code.md @@ -7,6 +7,8 @@ title: Working with native code on Windows > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + ## What is a React Native for Windows app? When you create a React Native for Windows app targeting React Native's old architecture, you will get a [Universal Windows Platform app](https://docs.microsoft.com/windows/uwp/get-started/universal-application-platform-guide) (aka UWP app). diff --git a/docs/native-modules-advanced.md b/docs/native-modules-advanced.md index 14ae6301d..29e31fac4 100644 --- a/docs/native-modules-advanced.md +++ b/docs/native-modules-advanced.md @@ -7,6 +7,8 @@ title: Native Modules (Advanced) > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + >**This documentation and the underlying platform code is a work in progress.** >**Examples (C# and C++/WinRT):** > - [Native Module Sample in `microsoft/react-native-windows-samples`](https://github.com/microsoft/react-native-windows-samples/tree/main/samples-old/NativeModuleSample) diff --git a/docs/native-modules-async.md b/docs/native-modules-async.md index d9049737c..518d7631e 100644 --- a/docs/native-modules-async.md +++ b/docs/native-modules-async.md @@ -7,6 +7,8 @@ title: Using Asynchronous Windows APIs > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + >**This documentation and the underlying platform code is a work in progress.** A common scenario for [Native Modules](native-modules.md) is to call one or more native asynchronous methods from a JS asynchronous method. However it may not be immediately obvious how to properly bridge both asynchronous worlds, which can lead to unstable, difficult to debug code. diff --git a/docs/native-modules-autolinking.md b/docs/native-modules-autolinking.md index 8459c3904..4f20dd074 100644 --- a/docs/native-modules-autolinking.md +++ b/docs/native-modules-autolinking.md @@ -7,6 +7,8 @@ title: Autolinking Native Modules > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + Autolinking is a mechanism that allows your React Native app project to discover and use native modules and view managers provided by React Native libraries. This document covers autolinking for the Windows platform. It is an extension to the [React Native CLI Autolinking doc](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md). diff --git a/docs/native-modules-csharp-codegen.md b/docs/native-modules-csharp-codegen.md index 5b267f026..fde3e4048 100644 --- a/docs/native-modules-csharp-codegen.md +++ b/docs/native-modules-csharp-codegen.md @@ -7,6 +7,8 @@ title: Compile time code generation for C# > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + >**This documentation and the underlying platform code is a work in progress.** In previous versions of React Native for Windows, code generation for C# modules was performed using reflection. Since 0.63 we improved this by adding a compile time code generation. diff --git a/docs/native-modules-jsvalue.md b/docs/native-modules-jsvalue.md index 95982fa88..de06ef510 100644 --- a/docs/native-modules-jsvalue.md +++ b/docs/native-modules-jsvalue.md @@ -7,6 +7,8 @@ title: Using JSValue > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + >**This documentation and the underlying platform code is a work in progress.** `JSValue` is a native, immutable invariant value type, and is meant to hold any of the commonly used JS types: `bool`s, `int`s, `double`s, `string`s, arrays, and objects. It is provided for native developers (writing native modules or view managers) who want an equivalent to the `folly::dynamic` type that is compatible with the WinRT ABI surface provided by `Microsoft.ReactNative`. diff --git a/docs/native-modules-marshalling-data.md b/docs/native-modules-marshalling-data.md index afb7a39b8..7a362228f 100644 --- a/docs/native-modules-marshalling-data.md +++ b/docs/native-modules-marshalling-data.md @@ -7,6 +7,8 @@ title: Marshaling Data > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + >**This documentation and the underlying platform code is a work in progress.** ## Overview diff --git a/docs/native-modules-setup.md b/docs/native-modules-setup.md index f3ab64bea..077f2e180 100644 --- a/docs/native-modules-setup.md +++ b/docs/native-modules-setup.md @@ -7,6 +7,8 @@ title: Native Module Setup > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + > **This documentation is a work in progress and version-specific. Please check that the version of this document (top of page) matches the version of RN/RNW you're targeting.** This guide will set you up with our recommendations for authoring a native module for React Native for Windows. After completing this setup, you should be able to answer the question: *Where do I need to implement the native code so it's available at runtime?* diff --git a/docs/native-modules-troubleshooting.md b/docs/native-modules-troubleshooting.md index effa49a65..67b1f8b09 100644 --- a/docs/native-modules-troubleshooting.md +++ b/docs/native-modules-troubleshooting.md @@ -7,6 +7,8 @@ title: Troubleshooting Native Modules > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + So you added a new native module or a new method to a module but it isn't working, **now what?!** ## Common Issues diff --git a/docs/native-modules-using.md b/docs/native-modules-using.md index eea7c20be..f08f9e56c 100644 --- a/docs/native-modules-using.md +++ b/docs/native-modules-using.md @@ -7,6 +7,8 @@ title: Using Community Native Modules > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + Community native modules are usually distributed as npm packages. To understand more about npm packages you may find [this guide](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) useful. Consuming native modules requires updating your app's native build files to depend on the module's native build files, called "linking". Many modules support "autolinking", where these updates are done automatically when running the [run-windows command](run-windows-cli.md). Others may require you to link the module manually. diff --git a/docs/native-modules-vs-turbo-modules.md b/docs/native-modules-vs-turbo-modules.md index 2e1e23014..68ce0f30a 100644 --- a/docs/native-modules-vs-turbo-modules.md +++ b/docs/native-modules-vs-turbo-modules.md @@ -7,6 +7,8 @@ title: Native Modules vs Turbo Modules > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + If you've worked with React Native, you may be familiar with the concept of Native Modules, which allow JavaScript and platform-native code to communicate over the React Native "bridge", which handles cross-platform serialization via JSON. TurboModules are the next iteration of Native Modules that provide a few extra benefits, in particular these modules use JSI, a JavaScript interface for native code, which allows for more efficient communication between native and JavaScript code than the bridge. diff --git a/docs/native-modules.md b/docs/native-modules.md index ee64c404c..8e825c3fc 100644 --- a/docs/native-modules.md +++ b/docs/native-modules.md @@ -7,6 +7,8 @@ title: Native Modules > **Architecture Review Needed:** This documentation was written to support development against React Native's "Old" or "Legacy" Architecture. It *may or may not* be directly applicable to New Architecture development and needs to be reviewed and potentially updated. For information on React Native architectures in React Native Windows, see [New vs. Old Architecture](new-architecture.md). +> For the latest information on native development on Windows, see [Native Platform: Overview](native-platform.md). + > **This documentation and the underlying platform code is a work in progress.** > **Examples (C# and C++/WinRT):** > diff --git a/docs/native-platform-components-paper.md b/docs/native-platform-components-paper.md new file mode 100644 index 000000000..50ce865c5 --- /dev/null +++ b/docs/native-platform-components-paper.md @@ -0,0 +1,376 @@ +--- +id: native-platform-components-paper +title: "Native Platform: Native Components (Paper)" +sidebar_label: Native Components (Paper) +--- + +![Architecture](https://img.shields.io/badge/architecture-old_only-yellow) + +This guide covers exposing native UI views from Windows to React Native by implementing a *Native Component* for the Windows platform. For a higher-level overview of native development on Windows, see [Native Platform: Overview](native-platform.md) before reading this guide. + +> **Note:** See the [reactnative.dev Native Components guide](https://reactnative.dev/docs/fabric-native-components-introduction) for steps for implementing new Native Components for both the Android and iOS platforms. + +> **Architecture Note:** This guide shows how to create a *Paper Native Component* to support React Native's Old Architecture. It will *not* work with New Architecture apps. To support React Native for Windows apps targeting the New Architecture, see [Native Platform: Native Components (Fabric)](native-platform-components.md). For more information on React Native architectures in React Native for Windows, see [New vs. Old Architecture](new-architecture.md). + +## High-Level Overview + +In order to implement Windows support for a Native Component, you'll need to: + +1. Define the API surface for your Native Component in a TypeScript spec files +2. Use React Native for Windows' Native Library Codegen to take the TypeScript spec files and create the C++ headers for the Windows code +3. Write the Windows C++ code to implement the *View Manager* +4. Use the Native Component in your JavaScript + +## Step by Step Guide + +### 0. Setup + +You'll need a React Native library project initialized with Windows support. + +> **Note:** The rest of this guide assumes you've followed the [Native Platform: Getting Started](native-platform-getting-started.md) guide to set up a new library project named `testlib`. + +### 1. Define the API surface in TypeScript + +The default template for a new library does not contain an example of a Native Component, so we'll need to make one. For this guide, we're going to implement a component that uses native UI code to force its child component to render within the bounds of a circle, masking out the corners. This `CircleMask` could be used to say, render a user's square account or profile image as a circle. + +First, we need to create the component's interface in a new TypeScript spec file `src\CircleMaskNativeComponent.ts`: + +```tsx +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type { ViewProps } from 'react-native'; + +export interface CircleMaskProps extends ViewProps {} + +export default codegenNativeComponent('CircleMask'); +``` + +This spec file declares that React Native expects every platform to implement a Native Component named `CircleMask` which supports the properties of `CircleMaskProps`. + +> **Note:** Every Native Component spec file must be named in the format ` + NativeComponent.ts` in order to be correctly identified as a spec file and not just a regular TypeScript file in your library. + +### 2. Use React Native for Windows' Native Library Codegen + +When making a Fabric Native Component, the React Native for Windows' Native Library Codegen is used to generate a bunch of C++ code to help you implement the Native Component. Unfortunately this generated code does not help with Paper Native Component implementations. See [Native Platform: Native Components (Fabric)](native-platform-components#2-use-react-native-for-windows-native-library-codegen) for more details. + +### 3. Implement the Windows C++ code + +Now it's time to implement `CircleMaskViewManager` in Windows code. React Native for Windows View Managers are implemented in C++ and render UI using the APIs in the `Windows::UI::Xaml` namespace, also known as [UWP XAML](https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/xaml-overview). + +#### 3.1 Implementing the Paper View Manager + +To create our new Paper View Manager we're going to need to create two new files (for our example, `CircleMask.h` and `CircleMask.cpp` in the `windows\testlib` folder): + + + + + +```cpp +#pragma once + +#include "pch.h" + +#ifndef RNW_NEW_ARCH + +#include +#include + +#endif + +namespace winrt::testlib::implementation { + +void RegisterCircleMaskNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; + +#ifndef RNW_NEW_ARCH + +struct CircleMaskViewManager : winrt::implements< + CircleMaskViewManager, + winrt::Microsoft::ReactNative::IViewManager, + winrt::Microsoft::ReactNative::IViewManagerWithChildren> { + public: + CircleMaskViewManager() {} + + // IViewManager + winrt::hstring Name() noexcept; + + winrt::Windows::UI::Xaml::FrameworkElement CreateView() noexcept; + + // IViewManagerWithChildren + + void AddView( + winrt::Windows::UI::Xaml::FrameworkElement const &parent, + winrt::Windows::UI::Xaml::UIElement const &child, + int64_t /*index*/) noexcept; + + void RemoveAllChildren(winrt::Windows::UI::Xaml::FrameworkElement const &parent) noexcept; + + void RemoveChildAt(winrt::Windows::UI::Xaml::FrameworkElement const &parent, int64_t /*index*/) noexcept; + + void ReplaceChild( + winrt::Windows::UI::Xaml::FrameworkElement const &parent, + winrt::Windows::UI::Xaml::UIElement const & /*oldChild*/, + winrt::Windows::UI::Xaml::UIElement const &newChild) noexcept; +}; + +struct HeightToCornerRadiusConverter + : winrt::implements { + public: + HeightToCornerRadiusConverter() {} + + winrt::Windows::Foundation::IInspectable Convert( + winrt::Windows::Foundation::IInspectable const &value, + winrt::Windows::UI::Xaml::Interop::TypeName const & /*targetType*/, + winrt::Windows::Foundation::IInspectable const & /*parameter*/, + winrt::hstring const & /*language*/) noexcept; + + winrt::Windows::Foundation::IInspectable ConvertBack( + winrt::Windows::Foundation::IInspectable const &value, + winrt::Windows::UI::Xaml::Interop::TypeName const & /*targetType*/, + winrt::Windows::Foundation::IInspectable const & /*parameter*/, + winrt::hstring const & /*language*/) noexcept; + + static winrt::Windows::UI::Xaml::Data::IValueConverter Instance() noexcept; + + // IValueConverter +}; + +#endif // #ifndef RNW_NEW_ARCH + +} // namespace winrt::testlib::implementation +``` + + + +```cpp +#include "pch.h" + +#include "CircleMask.h" + +namespace winrt::testlib::implementation { + +void RegisterCircleMaskNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept { +#ifndef RNW_NEW_ARCH + packageBuilder.AddViewManager(L"CircleMaskViewManager", []() { return winrt::make(); }); +#endif +} + +#ifndef RNW_NEW_ARCH + +// IViewManager +winrt::hstring CircleMaskViewManager::Name() noexcept { + return L"CircleMask"; +} + +winrt::Windows::UI::Xaml::FrameworkElement CircleMaskViewManager::CreateView() noexcept { + auto const &view = winrt::Windows::UI::Xaml::Controls::Border(); + + auto const &binding = winrt::Windows::UI::Xaml::Data::Binding(); + binding.Source(view); + binding.Path(winrt::Windows::UI::Xaml::PropertyPath(L"Height")); + binding.Converter(HeightToCornerRadiusConverter::Instance()); + + view.SetBinding(winrt::Windows::UI::Xaml::Controls::Border::CornerRadiusProperty(), binding); + + return view; +} + +// IViewManagerWithChildren + +void CircleMaskViewManager::AddView( + winrt::Windows::UI::Xaml::FrameworkElement const &parent, + winrt::Windows::UI::Xaml::UIElement const &child, + int64_t /*index*/) noexcept { + if (auto const &border = parent.try_as()) { + border.Child(child); + } +} + +void CircleMaskViewManager::RemoveAllChildren(winrt::Windows::UI::Xaml::FrameworkElement const &parent) noexcept { + if (auto const &border = parent.try_as()) { + border.Child(nullptr); + } +} + +void CircleMaskViewManager::RemoveChildAt( + winrt::Windows::UI::Xaml::FrameworkElement const &parent, + int64_t /*index*/) noexcept { + if (auto const &border = parent.try_as()) { + border.Child(nullptr); + } +} + +void CircleMaskViewManager::ReplaceChild( + winrt::Windows::UI::Xaml::FrameworkElement const &parent, + winrt::Windows::UI::Xaml::UIElement const & /*oldChild*/, + winrt::Windows::UI::Xaml::UIElement const &newChild) noexcept { + if (auto const &border = parent.try_as()) { + border.Child(newChild); + } +} + +winrt::Windows::Foundation::IInspectable HeightToCornerRadiusConverter::Convert( + winrt::Windows::Foundation::IInspectable const &value, + winrt::Windows::UI::Xaml::Interop::TypeName const & /*targetType*/, + winrt::Windows::Foundation::IInspectable const & /*parameter*/, + winrt::hstring const & /*language*/) noexcept { + double d = winrt::unbox_value(value); + + if (isnan(d)) { + d = 0.0; + } + + return winrt::box_value(winrt::Windows::UI::Xaml::CornerRadiusHelper::FromUniformRadius(d)); +} + +winrt::Windows::Foundation::IInspectable HeightToCornerRadiusConverter::ConvertBack( + winrt::Windows::Foundation::IInspectable const &value, + winrt::Windows::UI::Xaml::Interop::TypeName const & /*targetType*/, + winrt::Windows::Foundation::IInspectable const & /*parameter*/, + winrt::hstring const & /*language*/) noexcept { + return value; +} + +winrt::Windows::UI::Xaml::Data::IValueConverter HeightToCornerRadiusConverter::Instance() noexcept { + static auto const &instance = winrt::make(); + return instance; +}; + +#endif // #ifndef RNW_NEW_ARCH + +} // namespace winrt::testlib::implementation +``` + + + +As you can see, the `CircleMask.h` file defines three things: + +1. A `RegisterCircleMaskNativeComponent` function to register the `CircleMask` Paper View Manager with React Native +2. A `CircleMaskViewManager` struct containing the `CircleMask` Paper View Manager +3. A `HeightToCornerRadiusConverter` struct with some helper functionality + +Then within `CircleMask.cpp` we have the implementation specifics for our new Native Component. Note the use of `#ifndef RNW_NEW_ARCH` to ensure the Paper View Manager code is on included when the library is used by Old Architecture apps. + +> **Note:** For a more complete example of how to implement a `CircleMask` component for both Fabric and Paper simultaneously, see the implementation in the [Native Module Sample](https://github.com/microsoft/react-native-windows-samples/tree/main/samples/NativeModuleSample/cpp-lib) project. + +#### 3.2 Adding the Native Component's files to the native project + +Since we've created some new native files (`CircleMask.h` and `CircleMask.cpp` above), we need to make sure they are included in the native Windows project (`windows\testlib\testlib.vcxproj` and `windows\testlib\testlib.vcxproj.filters` in our example) so that they are included in the native build: + + + + + +```diff + + ++ + + ReactPackageProvider.idl + + + + + + + ++ + + Create + + + ReactPackageProvider.idl + + + +``` + + + +```diff + + + Header Files + + + Header Files + + + Header Files + ++ ++ Header Files ++ + + Header Files + + + + + Source Files + ++ ++ Source Files ++ + + Source Files + + +``` + + + +#### 3.3 Registering the Paper View Manager with the React Package Provider + +Every React Native for Windows library contains an [`IReactPackageProvider`](native-api/IReactPackageProvider-api-windows.md) which contains all of the library's Native Modules and/or Components so React Native can use them at runtime. The final bit of native work we need is to update `ReactPackageProvider::CreatePackage` in `windows\testlib\ReactPackageProvider.cpp`: + +```cpp +#include "pch.h" + +#include "ReactPackageProvider.h" +#if __has_include("ReactPackageProvider.g.cpp") +#include "ReactPackageProvider.g.cpp" +#endif + +#include "testlib.h" + +#include "CircleMask.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::testlib::implementation { + +void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { + AddAttributedModules(packageBuilder, true); + RegisterCircleMaskNativeComponent(packageBuilder); +} + +} // namespace winrt::testlib::implementation +``` + +The key bit here is adding the `#include "CircleMask.h"` include and adding the call to the `RegisterCircleMaskNativeComponent` function we created earlier. This makes sure the new Native Component is included in the library's package. + +### 4. Use the Native Component in your JavaScript + +Now, if we go back to the `CircleMaskNativeComponent.ts` TypeScript spec file, we'll see that exports the `CircleMaskProps` interface as well as the Native Component. The next step is to use those exported items in our JavaScript code. + +Since the purpose of the library is to expose the native functionality to code outside of the library (aka our React Native for Windows app code), the default is to export the functionality in the project's index, in this case, in `src\index.tsx`: + +```tsx +import Testlib from './NativeTestlib'; + +export function multiply(a: number, b: number): number { + return Testlib.multiply(a, b); +} + +export {default as CircleMask} from './CircleMaskNativeComponent'; +export * from './CircleMaskNativeComponent'; +``` + +We can see then, that `testlib` JavaScript module simply exports our new Native Component as `CircleMask` and everything else as-is from the `CircleMaskNativeComponent` module. + +> **Note:** Libraries are not required to expose any of their Native Components *directly* to their consumers. This sample just illustrates the simplest case of exporting the `CircleMask` Native Component as-is. Libraries can and often do wrap their Native Components within JavaScript ones, and therefore may provide a wholly different API surface to their customers. + +## Next Steps + +After you've implemented your native library, the final step is to consume it in your React Native for Windows app. Continue with [Native Platform: Using Native Libraries](native-platform-using.md). diff --git a/docs/native-platform-components.md b/docs/native-platform-components.md new file mode 100644 index 000000000..ad94ad8d3 --- /dev/null +++ b/docs/native-platform-components.md @@ -0,0 +1,418 @@ +--- +id: native-platform-components +title: "Native Platform: Native Components (Fabric)" +sidebar_label: Native Components (Fabric) +--- + +![Architecture](https://img.shields.io/badge/architecture-new_only-blue) + +This guide covers exposing native UI views from Windows to React Native by implementing a *Native Component* for the Windows platform. For a higher-level overview of native development on Windows, see [Native Platform: Overview](native-platform.md) before reading this guide. + +> **Note:** See the [reactnative.dev Native Components guide](https://reactnative.dev/docs/fabric-native-components-introduction) for steps for implementing new Native Components for both the Android and iOS platforms. + +> **Architecture Note:** This guide follows the recommendation to create a *Fabric Native Component* to support React Native's New Architecture. It will *not* work with Old Architecture apps. To support React Native for Windows apps targeting the Old Architecture, see [Native Platform: Native Components (Paper)](native-platform-components-paper.md). For more information on React Native architectures in React Native for Windows, see [New vs. Old Architecture](new-architecture.md). + +## High-Level Overview + +In order to implement Windows support for a Native Component, you'll need to: + +1. Define the API surface for your Native Component in a TypeScript spec files +2. Use React Native for Windows' Native Codegen to take the TypeScript spec files and create the C++ headers for the Windows code +3. Write the Windows C++ code to implement the *Component View* specified by the generated headers +4. Use the Native Component in your JavaScript + +## Step by Step Guide + +### 0. Setup + +You'll need a React Native library project initialized with Windows support. + +> **Note:** The rest of this guide assumes you've followed the [Native Platform: Getting Started](native-platform-getting-started.md) guide to set up a new library project named `testlib`. + +### 1. Define the API surface in TypeScript + +The default template for a new library does not contain an example of a Native Component, so we'll need to make one. For this guide, we're going to implement a component that uses native UI code to force its child component to render within the bounds of a circle, masking out the corners. This `CircleMask` could be used to say, render a user's square account or profile image as a circle. + +First, we need to create the component's interface in a new TypeScript spec file `src\CircleMaskNativeComponent.ts`: + +```tsx +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type { ViewProps } from 'react-native'; + +export interface CircleMaskProps extends ViewProps {} + +export default codegenNativeComponent('CircleMask'); +``` + +This spec file declares that React Native expects every platform to implement a Native Component named `CircleMask` which supports the properties of `CircleMaskProps`. + +> **Note:** Every Native Component spec file must be named in the format ` + NativeComponent.ts` in order to be correctly identified as a spec file and not just a regular TypeScript file in your library. + +### 2. Use React Native for Windows' Native Library Codegen + +Now, before we can implement the native C++ code for our Fabric Native Component(s), we need to run React Native for Windows' Native Library Codegen, i.e. the [codegen-windows command](codegen-windows-cli.md), which will take the TypeScript spec files and generate some C++ headers with the API surface we need to implement. + +First, we need to make sure that the `codegenConfig` object is properly defined in our library's `package.json` file: + +```json +"codegenConfig": { + "name": "RNTestlibSpec", + "type": "all", + "jsSrcsDir": "src", + "outputDir": { + "ios": "ios/generated", + "android": "android/generated" + }, + "android": { + "javaPackageName": "com.testlib" + }, + "includesGeneratedCode": true, + "windows": { + "namespace": "testlibCodegen", + "generators": [ + "modulesWindows", + "componentsWindows" + ], + "outputDirectory": "windows/testlib/codegen", + "separateDataTypes": true + } + } +``` + +Configuration is partially shared with other platforms, but for Windows the relevant fields are `type`, `jsSrcsDirs`, and the `windows` object. While the default configuration was correctly set up to support the library's Native Modules, we've needed to modify it to support our need for Native Components. + +Specifically, to enable Native Component codegen, we've changed `"type: "modules"` to `"type": "all"` and we've added the `"generators": [ "modulesWindows", "componentsWindows" ]` array. + +> **Note:** For more information on configuring `codegenConfig`, see [codegen-windows Codegen Config](codegen-windows-cli.md#codegen-config). + +The only thing we need to do now is run the codegen-windows command with: + +```bat +yarn react-native codegen-windows +``` + +> **Note:** By default the `codegen-windows` command is run automatically at the start of every native build. In this way, changes to the API surface in the TypeScript spec files will be reflected in the generated headers, thereby enforcing that the native code stays up to date with the required API surface of the component. + +Now we should see some files in the project's codegen output directory, i.e. the `windows\testlib\codegen` folder we specified in our config. Codegen files for Native Components are further put under the `react\components\RNTestlibSpec` folder. Specifically, for our `CircleMask` component, we should see a rather large `CircleMask.g.h` (truncated below): + +```cpp +/* + * This file is auto-generated from CircleMaskNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef It will not work with Old Architecture apps. + +#ifdef RNW_NEW_ARCH + +namespace testlibCodegen { + +REACT_STRUCT(CircleMaskProps) +struct CircleMaskProps : winrt::implements { + // Implementation truncated +}; + +struct CircleMaskEventEmitter { + // Implementation truncated +}; + +template +struct BaseCircleMask { + // Implementation truncated +}; + +template +void RegisterCircleMaskNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"CircleMask", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + // Implementation truncated + }); +} + +} // namespace testlibCodegen + +#endif // #ifdef RNW_NEW_ARCH +``` + +The generated code contains three native types of note: + +1. A `CircleMaskProps` struct capturing the specified props of the TypeScript `CircleMaskProps` interface +2. A `CircleMaskEventEmitter` struct so the component can fire any specified JavaScript events +3. A `BaseCircleMask` struct to be used as the base type for a `CircleMask` Fabric Component View +4. A `RegisterCircleMaskNativeComponent` function to register the `CircleMask` Fabric Component View + +Also note the use of `#ifdef RNW_NEW_ARCH` to ensure these types are only included when the library is used by New Architecture apps. + +> **Note:** For a non-truncated version of this file, see the [Native Module Sample's `CircleMask.g.h`](https://github.com/microsoft/react-native-windows-samples/blob/main/samples/NativeModuleSample/cpp-lib/windows/NativeModuleSample/codegen/react/components/NativeModuleSampleSpec/CircleMask.g.h). + +### 3. Implement the Windows C++ code + +Now with the codegen complete, it's time to implement a `CircleMaskComponentView` in Windows code. React Native for Windows Component Views are implemented in C++ and render UI using the APIs in the `Microsoft::UI::Composition` namespace, also known as the [Windows App SDK/WinUI 3 Visual layer](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/composition). + +#### 3.1 Implementing the Fabric Component View + +To create our new Fabric Component View we're going to need to create two new files (for our example, `CircleMask.h` and `CircleMask.cpp` in the `windows\testlib` folder): + + + + + +```cpp +#pragma once + +#include "pch.h" + +#ifdef RNW_NEW_ARCH + +#include "codegen/react/components/RNTestlibSpec/CircleMask.g.h" + +#include + +#endif + +namespace winrt::testlib::implementation { + +void RegisterCircleMaskNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; + +#ifdef RNW_NEW_ARCH + +struct CircleMaskComponentView : winrt::implements, + testlibCodegen::BaseCircleMask { + winrt::Microsoft::UI::Composition::Visual CreateVisual( + const winrt::Microsoft::ReactNative::ComponentView &view) noexcept override; + void Initialize(const winrt::Microsoft::ReactNative::ComponentView & /*view*/) noexcept override; + + private: + winrt::Microsoft::ReactNative::ComponentView::LayoutMetricsChanged_revoker m_layoutMetricChangedRevoker; + winrt::Microsoft::UI::Composition::SpriteVisual m_visual{nullptr}; +}; + +#endif // #ifdef RNW_NEW_ARCH + +} // namespace winrt::testlib::implementation +``` + + + +```cpp +#include "pch.h" + +#include "CircleMask.h" + +namespace winrt::testlib::implementation { + +void RegisterCircleMaskNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept { +#ifdef RNW_NEW_ARCH + testlibCodegen::RegisterCircleMaskNativeComponent( + packageBuilder, + [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { + // Turn off default border handling, as it overrides the Clip property of the visual and doesn't render + // correctly anyway This means we would have to implement drawing our own borders (which we don't do in this + // example) + builder.SetViewFeatures( + winrt::Microsoft::ReactNative::Composition::ComponentViewFeatures::Default & + ~winrt::Microsoft::ReactNative::Composition::ComponentViewFeatures::NativeBorder); + }); +#endif +} + +#ifdef RNW_NEW_ARCH + +winrt::Microsoft::UI::Composition::Visual CircleMaskComponentView::CreateVisual( + const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto compositor = view.as().Compositor(); + + m_visual = compositor.CreateSpriteVisual(); + + auto ellipseGeometry = compositor.CreateEllipseGeometry(); + auto clip = compositor.CreateGeometricClip(); + clip.Geometry(ellipseGeometry); + m_visual.Clip(clip); + + return m_visual; +} + +void CircleMaskComponentView::Initialize(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + m_layoutMetricChangedRevoker = view.LayoutMetricsChanged( + winrt::auto_revoke, + [wkThis = get_weak()]( + const winrt::IInspectable & /*sender*/, const winrt::Microsoft::ReactNative::LayoutMetricsChangedArgs &args) { + if (auto strongThis = wkThis.get()) { + auto visual = strongThis->m_visual; + + // Turning off default border handling has the side-effect of also stopping the visual from being positioned, + // so unless that changes we have to position the visual ourselves + // See https://github.com/microsoft/react-native-windows/issues/14706 + visual.Size( + {args.NewLayoutMetrics().Frame.Width * args.NewLayoutMetrics().PointScaleFactor, + args.NewLayoutMetrics().Frame.Height * args.NewLayoutMetrics().PointScaleFactor}); + visual.Offset({ + args.NewLayoutMetrics().Frame.X * args.NewLayoutMetrics().PointScaleFactor, + args.NewLayoutMetrics().Frame.Y * args.NewLayoutMetrics().PointScaleFactor, + 0.0f, + }); + + auto ellipseGeometry = strongThis->m_visual.Clip() + .as() + .Geometry() + .as(); + winrt::Windows::Foundation::Numerics::float2 radius = { + args.NewLayoutMetrics().Frame.Width * args.NewLayoutMetrics().PointScaleFactor / 2, + args.NewLayoutMetrics().Frame.Height * args.NewLayoutMetrics().PointScaleFactor / 2}; + ellipseGeometry.Center(radius); + ellipseGeometry.Radius(radius); + } + }); +} + +#endif // #ifdef RNW_NEW_ARCH + +} // namespace winrt::testlib::implementation +``` + + + +As you can see, the `CircleMask.h` file defines two things: + +1. A `RegisterCircleMaskNativeComponent` function to register the `CircleMask` Fabric Component View with React Native +2. A `CircleMaskComponentView` struct containing the `CircleMask` Fabric Component View + +Both of these depend on the types provided in the `CircleMask.g.h` file we generated earlier. Then within `CircleMask.cpp` we have the implementation specifics for our new Native Component. Again, note the use of `#ifdef RNW_NEW_ARCH` to ensure the Fabric Component View code is on included when the library is used by New Architecture apps. + +> **Note:** For a more complete example of how to implement a `CircleMask` component for both Fabric and Paper simultaneously, see the implementation in the [Native Module Sample](https://github.com/microsoft/react-native-windows-samples/tree/main/samples/NativeModuleSample/cpp-lib) project. + +#### 3.2 Adding the Native Component's files to the native project + +Since we've created some new native files (`CircleMask.h` and `CircleMask.cpp` above), we need to make sure they are included in the native Windows project (`windows\testlib\testlib.vcxproj` and `windows\testlib\testlib.vcxproj.filters` in our example) so that they are included in the native build: + + + + + +```diff + + ++ + + ReactPackageProvider.idl + + + + + + + ++ + + Create + + + ReactPackageProvider.idl + + + +``` + + + +```diff + + + Header Files + + + Header Files + + + Header Files + ++ ++ Header Files ++ + + Header Files + + + + + Source Files + ++ ++ Source Files ++ + + Source Files + + +``` + + + +> **Note:** All of the the headers created by codegen in the `windows/testlib/codegen` folder are already included and do not need to be added manually here. + +#### 3.3 Registering the Fabric Component View with the React Package Provider + +Every React Native for Windows library contains an [`IReactPackageProvider`](native-api/IReactPackageProvider-api-windows.md) which contains all of the library's Native Modules and/or Components so React Native can use them at runtime. The final bit of native work we need is to update `ReactPackageProvider::CreatePackage` in `windows\testlib\ReactPackageProvider.cpp`: + +```cpp +#include "pch.h" + +#include "ReactPackageProvider.h" +#if __has_include("ReactPackageProvider.g.cpp") +#include "ReactPackageProvider.g.cpp" +#endif + +#include "testlib.h" + +#include "CircleMask.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::testlib::implementation { + +void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { + AddAttributedModules(packageBuilder, true); + RegisterCircleMaskNativeComponent(packageBuilder); +} + +} // namespace winrt::testlib::implementation +``` + +The key bit here is adding the `#include "CircleMask.h"` include and adding the call to the `RegisterCircleMaskNativeComponent` function we created earlier. This makes sure the new Native Component is included in the library's package. + +### 4. Use the Native Component in your JavaScript + +Now, if we go back to the `CircleMaskNativeComponent.ts` TypeScript spec file, we'll see that exports the `CircleMaskProps` interface as well as the Native Component. The next step is to use those exported items in our JavaScript code. + +Since the purpose of the library is to expose the native functionality to code outside of the library (aka our React Native for Windows app code), the default is to export the functionality in the project's index, in this case, in `src\index.tsx`: + +```tsx +import Testlib from './NativeTestlib'; + +export function multiply(a: number, b: number): number { + return Testlib.multiply(a, b); +} + +export {default as CircleMask} from './CircleMaskNativeComponent'; +export * from './CircleMaskNativeComponent'; +``` + +We can see then, that `testlib` JavaScript module simply exports our new Native Component as `CircleMask` and everything else as-is from the `CircleMaskNativeComponent` module. + +> **Note:** Libraries are not required to expose any of their Native Components *directly* to their consumers. This sample just illustrates the simplest case of exporting the `CircleMask` Native Component as-is. Libraries can and often do wrap their Native Components within JavaScript ones, and therefore may provide a wholly different API surface to their customers. + +## Next Steps + +After you've implemented your native library, the final step is to consume it in your React Native for Windows app. Continue with [Native Platform: Using Native Libraries](native-platform-using.md). diff --git a/docs/native-platform-getting-started.md b/docs/native-platform-getting-started.md new file mode 100644 index 000000000..1996563bf --- /dev/null +++ b/docs/native-platform-getting-started.md @@ -0,0 +1,89 @@ +--- +id: native-platform-getting-started +title: "Native Platform: Getting Started" +sidebar_label: Getting Started +--- + +![Architecture](https://img.shields.io/badge/architecture-new_&_old-green) + +Similar to how the [Getting Started for Windows](getting-started.md) guide takes you through the process of creating a base React Native app (which supports iOS and Android), and then *adding* Windows support, this guide will take you through the steps of creating a base React Native library and then *adding* Windows support. + +Before you get started, make sure you have installed all of the [development dependencies](rnw-dependencies.md). + +> **Note:** There have always been multiple ways to create base React Native libraries, each creating a slightly different setup. This guide uses the `create-react-native-library` tool (with specific options) to start a brand new library, because that is the specific setup tested by the React Native for Windows team. Your experience may differ when attempting to add Windows support to (existing) libraries created by other tools. + +## Create a new React Native library project + +Call the following from the place where you want your project directory to live: + + + + + + + + +```bat +npx --yes create-react-native-library@0.48.9 --react-native-version "nightly" +``` + +> **Note:** Replace `` with the name of your library. The rest of this guide will assume you named your project `testlib`. + +You'll then be prompted for more information about the library you're trying to create (though you can also specify the answers at the command-line). Most are self-explanatory, but for this guide, you'll want to choose: + +| Option | Value | CLI Argument | +|:-------|:-------|:-------------| +| Package Name | testlib | `--slug testlib` | +| Library Type | Turbo module | `--type turbo-module` | +| Languages | Kotlin & Objective-C | `--languages kotlin-objc` | + +> **Note:** For more information on all of the available options, see [create-react-native-library's documentation](https://callstack.github.io/react-native-builder-bob). + +### Navigate into this newly created directory + +React Native will have created your project in a new sub-directory, which you must enter before continuing. + +```bat +cd testlib +``` + +### Add React Native for Windows to your project's node dependencies + + + + + + +```bat +yarn add react-native-windows@canary --dev +yarn add react-native-windows@* --peer +yarn install +``` + +### Initialize the React Native for Windows native code and projects + +Lastly, initialize the React Native for Windows library with the [init-windows command](init-windows-cli.md) and the `cpp-lib` template: + +```bat +npx react-native init-windows --template cpp-lib --overwrite +``` + +> **Note:** The command will not only initialize the Windows code for the library project itself, but it will also add and initialize React Native for Windows for the example app created by `create-react-native-library` in the `example` folder. + +## Running the React Native for Windows example app + +If you followed this guide and added Windows support to the base project created by `create-react-native-library`, you should be able to launch the provided `example` app with the [run-windows command](run-windows-cli.md): + +```bat +yarn react-native run-windows +``` + +> **Note:** For our `example` app, you can either run the given command from within the `example` folder, or run `yarn example react-native run-windows` directly from the library's root folder. + +## Next Steps + +After you've initialized a new project with Windows support, your next step is to implement the Windows support in native code. + +If you're implementing a Native Module (i.e. exposing non-UI native code), continue with [Native Platform: Native Modules](native-platform-modules.md). + +If you're implementing a Native Component (i.e. native Windows views), continue with [Native Platform: Native Components](native-platform-components.md). diff --git a/docs/native-platform-modules.md b/docs/native-platform-modules.md new file mode 100644 index 000000000..3e2942a54 --- /dev/null +++ b/docs/native-platform-modules.md @@ -0,0 +1,338 @@ +--- +id: native-platform-modules +title: "Native Platform: Native Modules" +sidebar_label: Native Modules +--- + +![Architecture](https://img.shields.io/badge/architecture-new_&_old-green) + +This guide covers exposing native non-UI functionality from Windows to React Native by implementing a *Native Module* for the Windows platform. For a higher-level overview of native development on Windows, see [Native Platform: Overview](native-platform.md) before reading this guide. + +> **Note:** See the [reactnative.dev Native Modules guide](https://reactnative.dev/docs/turbo-native-modules-introduction) for steps for implementing new Native Modules for both the Android and iOS platforms. + +> **Architecture Note:** This guide follows the recommendation to create a *Turbo Native Module* to support React Native's New Architecture. However, unlike other platforms, React Native for Windows directly supports Turbo Native Modules for the Old Architecture as well. In short, the Turbo Native Module we create here can be consumed by React Native for Windows apps targeting *either* architecture. For more information on React Native architectures in React Native for Windows, see [New vs. Old Architecture](new-architecture.md). + +## High-Level Overview + +In order to implement Windows support for a Native Module, you'll need to: + +1. Define the API surface for your Native Module in a TypeScript spec file +2. Use React Native for Windows' Native Library Codegen to take the TypeScript spec files and create the C++ headers for the Windows code +3. Write the Windows C++ code to implement the functions specified in the generated headers +4. Use the Native Module in your JavaScript + +## Step by Step Guide + +### 0. Setup + +You'll need a React Native library project initialized with Windows support. + +> **Note:** The rest of this guide assumes you've followed the [Native Platform: Getting Started](native-platform-getting-started.md) guide to set up a new library project named `testlib`. + +### 1. Define the API surface in TypeScript + +The default template for a new library starts with a simple Turbo Native Module based on the name of the project, i.e. our `testlib` project contains a `TestLib` module, whose API surface is defined in `src\NativeTestlib.ts`: + +```ts +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + multiply(a: number, b: number): number; +} + +export default TurboModuleRegistry.getEnforcing('Testlib'); +``` + +This spec file declares that React Native expects every platform to implement a Turbo Native Module named `Testlib` which implements a single function named `multiply` with the given arguments and return type. + +> **Note:** Every Native Module spec file must be named in the format `Native + .ts` in order to be correctly identified as a spec file and not just a regular TypeScript file in your library. + + + +### 2. Use React Native for Windows' Native Library Codegen + +Now, before we can implement the native C++ code for our Turbo Native Module(s), we need to run React Native for Windows' Native Library Codegen, i.e. the [codegen-windows command](codegen-windows-cli.md), which will take the TypeScript spec files and generate some C++ headers with the API surface we need to implement. + +First, we need to make sure that the `codegenConfig` object is properly defined in our library's `package.json` file: + +```json +"codegenConfig": { + "name": "RNTestlibSpec", + "type": "modules", + "jsSrcsDir": "src", + "outputDir": { + "ios": "ios/generated", + "android": "android/generated" + }, + "android": { + "javaPackageName": "com.testlib" + }, + "includesGeneratedCode": true, + "windows": { + "namespace": "testlibCodegen", + "outputDirectory": "windows/testlib/codegen", + "separateDataTypes": true + } + } +``` + +Configuration is partially shared with other platforms, but for Windows the relevant fields are `type`, `jsSrcsDirs`, and the `windows` object. For now we're going to leave the configuration as-is, as it is already set up to support our `Testlib` module. + +> **Note:** For more information on configuring `codegenConfig`, see [codegen-windows Codegen Config](codegen-windows-cli.md#codegen-config). + +The only thing we need to do now is run the codegen-windows command with: + +```bat +yarn react-native codegen-windows +``` + +> **Note:** By default the `codegen-windows` command is run automatically at the start of every native build. In this way, changes to the API surface in the TypeScript spec files will be reflected in the generated headers, thereby enforcing that the native code stays up to date with the required API surface of the module. + +Now we should see some files in the project's codegen output directory, i.e. the `windows\testlib\codegen` folder we specified in our config. Specifically, for our `Testlib` module, we should see a `NativeTestlibSpec.g.h` with: + +```cpp +/* + * This file is auto-generated from a NativeModule spec file in js. + * + * This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules + * in a way that also verifies at compile time that the native module matches the interface required + * by the TurboModule JS spec. + */ +#pragma once +// clang-format off + + +#include +#include + +namespace testlibCodegen { + +struct TestlibSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { + static constexpr auto methods = std::tuple{ + SyncMethod{0, L"multiply"}, + }; + + template + static constexpr void ValidateModule() noexcept { + constexpr auto methodCheckResults = CheckMethods(); + + REACT_SHOW_METHOD_SPEC_ERRORS( + 0, + "multiply", + " REACT_SYNC_METHOD(multiply) double multiply(double a, double b) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(multiply) static double multiply(double a, double b) noexcept { /* implementation */ }\n"); + } +}; + +} // namespace testlibCodegen +``` + +The purpose of the `TestlibSpec` type in this file, when included in our native C++ project, is to throw errors if our native C++ implementation does not match the required API surface of the module. + + + +### 3. Implement the Windows C++ code + +Now with the codegen complete, it's finally time to implement the `Testlib` module and its `multiply()` function. + +#### 3.1 Implementing the Turbo Native Module + +Conveniently our new project already includes implementations we can look at (for our example, the `testlib.h` and `testlib.cpp` in the `windows\testlib` folder): + + + + + +```cpp +#pragma once + +#include "pch.h" +#include "resource.h" + +#if __has_include("codegen/NativeTestlibDataTypes.g.h") + #include "codegen/NativeTestlibDataTypes.g.h" +#endif +#include "codegen/NativeTestlibSpec.g.h" + +#include "NativeModules.h" + +namespace winrt::testlib +{ + +REACT_MODULE(Testlib) +struct Testlib +{ + using ModuleSpec = testlibCodegen::TestlibSpec; + + REACT_INIT(Initialize) + void Initialize(React::ReactContext const &reactContext) noexcept; + + REACT_SYNC_METHOD(multiply) + double multiply(double a, double b) noexcept; + +private: + React::ReactContext m_context; +}; + +} // namespace winrt::testlib +``` + + + +```cpp +#include "pch.h" + +#include "testlib.h" + +namespace winrt::testlib +{ + +// See https://microsoft.github.io/react-native-windows/docs/native-platform for details on writing native modules + +void Testlib::Initialize(React::ReactContext const &reactContext) noexcept { + m_context = reactContext; +} + +double Testlib::multiply(double a, double b) noexcept { + return a * b; +} + +} // namespace winrt::testlib +``` + + + +As you can see, the `testlib.h` file defines a `Testlib` struct, attributed with `REACT_MODULE` to signify to React Native for Windows that this struct contains the implementation of the Turbo Native Module named `Testlib`. + +The `using ModuleSpec = testlibCodegen::TestlibSpec;` line is what makes sure that the `Testlib` struct will fail to compile if it doesn't meet the required API surface of the module. + +> **Note:** When adding Windows support to native modules with out-of-date (or missing) spec files, removing this line will allow your native code to compile even if it doesn't match what the JavaScript side of the library expects. While possible, this is not recommended as it risks the Windows implementation of the module getting out of sync with the other platforms. + +The `Initialize()` function is attributed with `REACT_INIT`, indicating it should be run when the module is first created. Looking at the implementation in `testlib.cpp` we see it saves off a [`ReactContext`](native-api/IReactContext-api-windows.md), which your module can later use to interact back with the JavaScript side of your code (i.e. firing JavaScript events during a native operation). + +Finally, we also see the `multiply()` function is attributed with `REACT_SYNC_METHOD`, indicating that the function is part of the module's API surface, but also synchronous. Looking at the implementation in `testlib.cpp` we see it does what we'd expect, multiplying the input parameters and returning the result. + + + +#### 3.2 Adding the Turbo Native Modules's files to the native project + +By default the native Windows project (`windows\testlib\testlib.vcxproj` and `windows\testlib\testlib.vcxproj.filters` in our example) already includes the `testlib.h` and `testlib.cpp` files. But if you create new files for your module, you'll need to add those to the native Windows project manually: + + + + + +```diff + + ++ + + ReactPackageProvider.idl + + + + + + + ++ + + Create + + + ReactPackageProvider.idl + + + +``` + + + +```diff + + + Header Files + + + Header Files + + + Header Files + ++ ++ Header Files ++ + + Header Files + + + + + Source Files + ++ ++ Source Files ++ + + Source Files + + +``` + + + +> **Note:** All of the the headers created by codegen in the `windows/testlib/codegen` folder are already included and do not need to be added manually here. + +#### 3.3 Registering the Turbo Native Module with the React Package Provider + +Every React Native for Windows library contains an [`IReactPackageProvider`](native-api/IReactPackageProvider-api-windows.md) which contains all of the library's Native Modules and/or Components so React Native can use them at runtime. + +The final bit of native work we need is to make sure `ReactPackageProvider::CreatePackage` adds all the attributed modules in `windows\testlib\ReactPackageProvider.cpp`: + +```cpp +#include "pch.h" + +#include "ReactPackageProvider.h" +#if __has_include("ReactPackageProvider.g.cpp") +#include "ReactPackageProvider.g.cpp" +#endif + +#include "testlib.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::testlib::implementation { + +void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { + AddAttributedModules(packageBuilder, true); +} + +} // namespace winrt::testlib::implementation +``` + +Conveniently our new project already includes the code to include our `Testlib` Turbo Native Module. + +The key bit here is the `#include "testlib.h"` include and the call to the `AddAttributedModules` function. This call makes sure that every Turbo Native Module (every struct attributed with `REACT_MODULE`), from every included header file, gets included in the library's package. + +### 4. Use the Native Module in your JavaScript + +Now, if we go back to the `NativeTestlib.ts` TypeScript spec file, we'll see that exports a type that is the Turbo Native Module named `Testlib` with an interface matching `Spec`. The next step is to use that exported object in our JavaScript code. + +Since the purpose of the library is to expose the native functionality to code outside of the library (aka our React Native for Windows app code), the default is to export the functionality in the project's index, in this case, in `src\index.tsx`: + +```tsx +import Testlib from './NativeTestlib'; + +export function multiply(a: number, b: number): number { + return Testlib.multiply(a, b); +} +``` + +We can see then, that the `testlib` JavaScript module exports a `multiply()` function which internally simply calls the `Testlib.multiply()` function. + +> **Note:** Libraries are not required to expose any of their Native Module functions directly to their consumers. This sample just illustrates the simplest case of a pass-through call to the Native Module function. Libraries can and often do have lots of functionality written in JavaScript, and may provide a wholly different API surface to their customers. + +## Next Steps + +After you've implemented your native library, the final step is to consume it in your React Native for Windows app. Continue with [Native Platform: Using Native Libraries](native-platform-using.md). diff --git a/docs/native-platform-using.md b/docs/native-platform-using.md new file mode 100644 index 000000000..4e295e9fc --- /dev/null +++ b/docs/native-platform-using.md @@ -0,0 +1,211 @@ +--- +id: native-platform-using +title: "Native Platform: Using Native Libraries" +sidebar_label: Using Native Libraries +--- + +![Architecture](https://img.shields.io/badge/architecture-new_&_old-green) + +This guide covers how to consume Native Modules (and/or Components) from a native library in a React Native for Windows app. For a higher-level overview of developing native, see [Native Platform: Overview](native-platform.md) before reading this guide. + +> **Note:** The instructions below are generalized and should work with most native libraries, however specific libraries may have their own instructions and/or additional installation steps. + +## High-Level Overview + +In order to use a native library in a React Native for Windows app, you'll need to: + +1. Add the native library package as a Node.js dependency to the app +2. Use React Native for Windows' Native Module Autolinking to connect the library's Windows project to the app's Windows project +3. Call the native library's API surface from within the app's JavaScript code + +## Step by Step Guide + +### 0. Setup + +You'll need a React Native library project with Windows support initialized and implemented. + +> **Note:** The rest of this guide assumes you've at least followed the [Native Platform: Native Modules](native-platform-modules.md) guide to create and implement a new library project named `testlib`, and you're going to consume it via the provided app in its `example` folder. + +### 1. Add the native library package as a Node.js dependency to the app + +The first thing you'll need to do is add the native library's Node.js package as a dependency of your React Native app if it isn't already: + +```bat +yarn add testlib +``` + +> **Note:** While this is the standard way of adding the library package as a dependency of your app (especially if you publish the library to, and are consuming it from, a NPM feed) this is *not* how the provided `example` app consumes the library. The `example` app instead uses a custom entry in the `dependencies` object of its `react-native.config.js` configuration. + +### 2. Use React Native for Windows' Native Module Autolinking + +Now, before we can successfully consume the native library in our React Native for Windows app we need to run React Native for Windows' autolinking, i.e. the [autolink-windows command](autolink-windows-cli.md), at least once, to properly connect the library's native Windows projects to our app's native Windows project: + +```bat +yarn react-native autolink-windows +``` + +> **Note:** For our `example` app, you can either run the given command from within the `example` folder, or run `yarn example react-native autolink-windows` directly from the library's root folder. + +The command will (re-)generate several native files under the app's `windows` folder, (for the `example` app, under `example\windows\testLibExample`), including: + + + + + +```xml + + + + + + + {4AA0750A-2B4A-4DE1-BD39-B65A83AADE6B} + + + +``` + + + +```cpp +// AutolinkedNativeModules.g.cpp contents generated by "npx @react-native-community/cli autolink-windows" +// clang-format off +#include "pch.h" +#include "AutolinkedNativeModules.g.h" + +// Includes from testlib +#include + +namespace winrt::Microsoft::ReactNative +{ + +void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) +{ + // IReactPackageProviders from testlib + packageProviders.Append(winrt::testlib::ReactPackageProvider()); +} + +} +``` + + + +```xml + + + + + + +``` + + + +```cpp +// AutolinkedNativeModules.g.h contents generated by "npx @react-native-community/cli autolink-windows" +// clang-format off +#pragma once + +namespace winrt::Microsoft::ReactNative +{ + +void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders); + +} +``` + + + +> **Note:** The generated files include the necessary setup to connect *all* of the native libraries to the React Native for Windows app. + +The `AutolinkedNativeModules.g.targets` (and `AutolinkedNativeModules.g.props`) files contain the build configuration such that the native Windows app project depends on each native Windows library project. + +The `AutolinkedNativeModules.g.cpp` (and `AutolinkedNativeModules.g.h`) files define a function which returns the list containing each library's [`IReactPackageProvider`](native-api/IReactPackageProvider-api-windows.md) (which in turn contains each library's Native Modules and/or Components), so that these libraries can be added to React Native's list of registered packages at runtime. + +> **Note:** By default, the usual [run-windows command](run-windows-cli.md) will also automatically run autolinking before building a React Native for Windows app. + +### 3. Call the native library's API surface + +With the native library properly connected to the React Native for Windows app, the app's JavaScript should now be able to call the library's JavaScript APIs at runtime and expect the native functionality to be available. That is, each time the library's JavaScript needs to access its Native Modules (and/or Components), they will already be ready and registered on the native side. + +#### 3.1 Use a Native Module's API + +If your library implements and exports any APIs which use Native Modules, you can import and call them from your JavaScript. + +For our `example` app, we can see the library's `multiply` function being imported and used in `example\src\App.tsx`: + +```tsx +import { Text, View, StyleSheet } from 'react-native'; +import { multiply } from 'testlib'; + +const result = multiply(3, 7); + +export default function App() { + return ( + + Result: {result} + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, +}); +``` + +#### 3.2 Use a Native Component + +If your library implements and exports any components which use Native Components, you can also import and use them from your JavaScript. + +For our `example` app, if you followed the [Native Platform: Native Components](native-platform-components.md) guide, we can see the library's `CircleMask` component being imported and used in this `example\src\App.tsx`: + +```tsx +import { Text, View, StyleSheet } from 'react-native'; +import { multiply, CircleMask } from 'testlib'; + +const result = multiply(3, 7); + +export default function App() { + return ( + + + + Result: {result} + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, +}); +``` + +> **Note:** The default `example` app provided is a New Architecture app and cannot be used to test Paper Native Components. + +#### 3.3 Verifying the functionality + +To verify the functionality works end-to-end, you should be able to launch the provided `example` app with the [run-windows command](run-windows-cli.md): + +```bat +yarn react-native run-windows +``` + +> **Note:** For our `example` app, you can either run the given command from within the `example` folder, or run `yarn example react-native run-windows` directly from the library's root folder. diff --git a/docs/native-platform.md b/docs/native-platform.md new file mode 100644 index 000000000..1b72c8cad --- /dev/null +++ b/docs/native-platform.md @@ -0,0 +1,37 @@ +--- +id: native-platform +title: "Native Platform: Overview" +sidebar_label: Overview +--- + +![Architecture](https://img.shields.io/badge/architecture-new_&_old-green) + +Sometimes a React Native app needs to access native functionality that isn't already exposed via `react-native` or an existing community module or library. Whether it's to access a platform API or some other custom native code, React Native was designed to be extensible, making it possible for anyone to write native code and expose that functionality to their app's JavaScript. + +The [reactnative.dev Native Platform guide](https://reactnative.dev/docs/native-platform) defines *Native Modules* as native libraries for accessing non-UI native code, and *Native Components* for accessing native platform views. That guide includes steps for implementing new Native Modules (and/or Components) for both the Android and iOS platforms. This guide will cover how to implement new Native Modules (and/or Components) for the Windows platform. + +> **Architecture Note:** The React Native guide recommends creating *Turbo Native Modules* and/or *Fabric Native Components* to support React Native's New Architecture, rather than the legacy APIs made for the Old Architecture. This guide will detail how to create a single library which supports both architectures on Windows. For more information on React Native architectures in React Native for Windows, see [New vs. Old Architecture](new-architecture.md). + +## Getting Started + +Your first step to implement a new Native Module (and/or Component) is to create a new base native library and initialize React Native for Windows support. See [Native Platform: Getting Started](native-platform-getting-started.md). + +## Implementing Windows Support + +After you've initialized a new project with Windows support, your next step is to implement the Windows support in native code. + +If you're implementing a Native Module (i.e. exposing non-UI native code), continue with [Native Platform: Native Modules](native-platform-modules.md). + +If you're implementing a Native Component (i.e. native Windows views), continue with [Native Platform: Native Components](native-platform-components.md). + +## Using Native Libraries on Windows + +After you've implemented your native library, the final step is to consume it in your React Native for Windows app. Continue with [Native Platform: Using Native Libraries](native-platform-using.md). + +## Native Module Sample + +The [Native Module Sample](https://github.com/microsoft/react-native-windows-samples/tree/main/samples/NativeModuleSample/cpp-lib) project is a complete React Native for Windows Library that contains: + +* Several Native Modules examples +* A Native Component example with implementations for both Paper and Fabric +* Both New and Old Architecture example apps diff --git a/docs/run-windows-cli.md b/docs/run-windows-cli.md index ce83608f5..4120e8ec7 100644 --- a/docs/run-windows-cli.md +++ b/docs/run-windows-cli.md @@ -49,7 +49,9 @@ Here are the options that `react-native run-windows` takes: | `--no-telemetry` | boolean | Disables sending telemetry that allows analysis of usage and failures of the react-native-windows CLI | | `-h`, `--help` | boolean | Display help for command | -This sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. +## Telemetry Notice + +This command sends telemetry to Microsoft by default. You can prevent the telemetry from being sent by using the `--no-telemetry` command line option. See below for more details. The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/website/sidebars.json b/website/sidebars.json index 644a8f558..63b17f70d 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -11,7 +11,8 @@ "platform", "upgrade-app", "setup-ci", - "app-publishing" + "app-publishing", + "supported-community-modules" ], "CLI Commands (Windows)": [ "autolink-windows-cli", @@ -19,26 +20,18 @@ "init-windows-cli", "run-windows-cli" ], - "Native Modules (Windows)": [ - "native-modules", - "view-managers", - "native-modules-setup", - "native-modules-vs-turbo-modules", - "native-modules-using", - "native-modules-autolinking", - "native-modules-advanced", - "supported-community-modules" - ], "Native Development (Windows)": [ - "native-code", - "native-code-language-choice", - "native-modules-marshalling-data", - "native-modules-async", - "native-modules-jsvalue", - "native-modules-csharp-codegen", + "native-platform", + "native-platform-getting-started", + "native-platform-modules", + "native-platform-components", + "native-platform-components-paper", + "native-platform-using" + ], + "Advanced Topics (Windows)": [ "win10-vm", - "customizing-sdk-versions", - "managing-cpp-deps" + "hermes", + "NuGet" ], "The Basics (MacOS)": [ "rnm-getting-started", @@ -46,13 +39,37 @@ ], "Troubleshooting": [ "debugging-javascript", - "native-modules-troubleshooting", "metro-config-out-tree-platforms" ], - "Experimental" : [ - "new-architecture", - "hermes", - "NuGet" + "Legacy Docs": [ + { + "type": "subcategory", + "label": "Native Modules (Windows)", + "ids": [ + "native-modules", + "view-managers", + "native-modules-setup", + "native-modules-vs-turbo-modules", + "native-modules-using", + "native-modules-autolinking", + "native-modules-advanced", + "native-modules-troubleshooting" + ] + }, + { + "type": "subcategory", + "label": "Native Development (Windows)", + "ids": [ + "native-code", + "native-code-language-choice", + "native-modules-marshalling-data", + "native-modules-async", + "native-modules-jsvalue", + "native-modules-csharp-codegen", + "customizing-sdk-versions", + "managing-cpp-deps" + ] + } ] }, "apis": { @@ -83,8 +100,7 @@ "native-api/ReactInstanceSettings", "native-api/ReactNativeHost", "native-api/XamlUIService", - "native-api/Native-API-Reference", - "coreapp" + "native-api/Native-API-Reference" ] } } diff --git a/website/versioned_docs/version-0.78/getting-started.md b/website/versioned_docs/version-0.78/getting-started.md index ea2dcd49f..935d0e48a 100644 --- a/website/versioned_docs/version-0.78/getting-started.md +++ b/website/versioned_docs/version-0.78/getting-started.md @@ -26,7 +26,7 @@ Remember to call `@react-native-community/cli init` from the place you want your ```bat -npx --yes @react-native-community/cli@next init --version ^0.78.0 +npx --yes @react-native-community/cli@latest init --version ^0.78.0 ``` ### Navigate into this newly created directory