microsoft / react-native-windows

A framework for building native Windows apps with React.
https://microsoft.github.io/react-native-windows/
Other
16.33k stars 1.14k forks source link

How to render different content in different screens? #8424

Closed wecliang closed 3 years ago

wecliang commented 3 years ago

I have ask question about “How to use react-native-windows to support multiple screens to display different contents #8309”,and I follow the suggest。

Now I have create two pages for different use and show them at the same time。But there seems something wrong with the render() method。I need some help。

First I regist two rn component at index.js

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import RNComponent from './src/pages/secondScreen/index';`

AppRegistry.registerComponent(appName, () => App);
AppRegistry.registerComponent('RNComponent', () => RNComponent);

Second I create two pages.

MainPage.xaml

<Page
    x:Class="shopclient.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:shopclient"
    xmlns:react="using:Microsoft.ReactNative"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <react:ReactRootView 
        x:Name="ReactRootView"
        ComponentName="shopClient"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        MinHeight="400"/>
</Page>

MainPage.cpp

namespace winrt::shopclient::implementation
{
    MainPage::MainPage()
    {
        InitializeComponent();
        auto app = Application::Current().as<App>();
        ReactRootView().ReactNativeHost(app->Host());
    }
}

SceondScreenpage.xaml

<Page
    x:Class="shopclient.SecondScreenPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:shopclient"
    xmlns:react="using:Microsoft.ReactNative"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <react:ReactRootView 
        x:Name="ReactRootView1"
        ComponentName="RNComponent"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        MinHeight="400"/>
</Page>

SceondScreenPage.cpp

namespace winrt::shopclient::implementation
{
    SecondScreenPage::SecondScreenPage()
    {
        InitializeComponent();
        auto app = Application::Current().as<App>();
        ReactRootView1().ReactNativeHost(app->Host());
    }
}

And this is how to create tow screens。I write it in App.cpp

App.cpp

    void App::OnLaunched(activation::LaunchActivatedEventArgs const& e)
    {
        super::OnLaunched(e);

        ApplicationView view = ApplicationView::GetForCurrentView();
        //view.TryEnterFullScreenMode();

        //Application::Current().Exit();

        Frame rootFrame = Window::Current().Content().as<Frame>();
        rootFrame.Navigate(xaml_typename<MainPage>(), box_value(e.Arguments()));

        // create second screen
        CreateSecondScreenView(e);
    }
    fire_and_forget App::CreateSecondScreenView(activation::LaunchActivatedEventArgs const& e)
    {
        int newViewId = 0;
        winrt::Windows::UI::Core::CoreDispatcher dispatcher
            = winrt::Windows::ApplicationModel::Core::CoreApplication::CreateNewView().Dispatcher();

        co_await dispatcher.RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
            [&]()
            {
                winrt::Windows::UI::Xaml::Controls::Frame rootFrame1 = winrt::Windows::UI::Xaml::Controls::Frame();
                rootFrame1.Navigate(xaml_typename<SecondScreenPage>(), box_value(e.Arguments()));
                Window::Current().Content(rootFrame1);
                Window::Current().Activate();
                newViewId = winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView().Id();
            });
        co_await winrt::Windows::UI::ViewManagement::ApplicationViewSwitcher::TryShowAsStandaloneAsync(newViewId);
    }

When I run the project , it crashed( WinRT originate error - 0x8001010E : ). It seems like I should create two "appXXX" for different use? One for companent "shopClient",and another for "RNCompanent"? I don't know the real reason. Any help???

chrisglein commented 3 years ago

When I run the project , it crashed( WinRT originate error - 0x8001010E

This error code indicates RPC_E_WRONG_THREAD, as in there is code that is supposed to execute on the UI thread that is not. If you were updating your app from a previous version to 0.64+, you may be running into the change in thread affinity (see breaking changes here). Check the thread your error is originating from and your potential fix is to use the dispatcher to execute it on the UI thread (check docs for more info like this).

ghost commented 3 years ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 7 days. It will be closed if no further activity occurs within 14 days of this comment.

acoates-ms commented 2 years ago

In UWP applications, each top level window (CreateNewView) gets its own UI thread. A react-native instance can only be run against a single UI thread. So to have two top level windows use RN content, you'll need to have two seperate RN instances running. (So two ReactNativeHosts)