Skip to content
This repository has been archived by the owner on Mar 7, 2024. It is now read-only.

在 App 上创建 React 实例 #189

Merged
merged 2 commits into from
Sep 2, 2019
Merged

在 App 上创建 React 实例 #189

merged 2 commits into from
Sep 2, 2019

Conversation

yesmeck
Copy link
Member

@yesmeck yesmeck commented Aug 30, 2019

背景

小程序本身是个多页应用。目前 Remax 的实现也是在每个页面上创建一个 React 实例

问题

多页导致的问题就是数据共享,多个 React 实例间没办法通过 Context 来共享状态,这也是为什么现在没办法直接在 Remax 上用 redux 的原因(#122)。

解法

这个 PR 尝试在 App 上创建一个 React 实例,然后每个页面再通过 portal 各自渲染到自己的 container 上。

这样做的好处就是我们 App 变成了整个应用的总入口:

// TodoContext.js
import * as React from 'react';

const TodoContext = React.createContext([]);

export default TodoContext;
// app.js
import * as React from 'react';
import './app.css';
import TodoContext from './TodoContext';

class App extends React.Component {
  render() {
    return (
      <TodoContext.Provider
        value={[
          { id: 1, text: 'Learning Javascript', completed: true },
          { id: 2, text: 'Learning ES2016', completed: true },
          { id: 3, text: 'Learning Remax', completed: false },
        ]}
      >
        {this.props.children}
      </TodoContext.Provider>
    );
  }
}

export default App;

这也意味着我们可以以非常小的成本去接入类似 redux 这种需要一个全局 Provider 的库(#152)。页面间的状态共享完全可以用 Context 的方式来实现,更加的 React 了!

@yesmeck yesmeck changed the base branch from master to develop August 30, 2019 18:44
@yesmeck yesmeck changed the title 在 App 上创建 React 实例 [WIP]在 App 上创建 React 实例 Aug 30, 2019
@Darmody
Copy link
Contributor

Darmody commented Aug 30, 2019

可以在 App 里面挂载全局组件共用组件吗?

@Darmody
Copy link
Contributor

Darmody commented Aug 30, 2019

可以在 App 里面挂载全局组件吗?

应该是可以的吧?这就非常好了

@yesmeck
Copy link
Member Author

yesmeck commented Aug 31, 2019

App 上的基础组件现在是不会渲染的,也就是说下面的 View 是不会渲染到页面上的。

class App extends React.Component {
  render() {
    return (
     <View id="app">
        {this.props.children}
      </View>
    );
  }
}


render() {
render(
React.createElement(App, null, this.pages.map(p => p.element)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在这里处理一下呢

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我是不打算支持。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

什么原因呢

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没什么用,支持这个能用的地方就是做 Layout,但是现在 App 里是没法区分当前渲染的哪个页面的,也就是没办法不同的页面不同 Layout,有点鸡肋。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没事不用区分。

现在小程序自定义头部,tabBar,Modal等等,都是每个页面重复引入,对这块很有帮助

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

太复杂了。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不对,这种思路还是全局组件

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该是页面挂载的时候,把共用组件带入一起渲染

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

然后要怎么通信,开发者自己决定就好了

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

试了一下,确实很鸡肋。

@Darmody
Copy link
Contributor

Darmody commented Aug 31, 2019

可以在 App 里面挂载全局组件吗?

不是全局组件,这个定义应该是共用组件,就是每个页面都会重复引入的组件。如自定义头部,自定义底部,自定义 Modal 等等。

写起来太麻烦了

@Darmody
Copy link
Contributor

Darmody commented Aug 31, 2019

App 上的基础组件现在是不会渲染的,也就是说下面的 View 是不会渲染到页面上的。

class App extends React.Component {
  render() {
    return (
     <View id="app">
        {this.props.children}
      </View>
    );
  }
}

这样的写法会让开发者感到困惑,明明是个 React 组件,但是不能真正渲染。 Taro 的 app 文件就是这么写的。

是不是可以改成在 App 里提供 injectProviders 的方式,而不是 React 组件

@Pochodaydayup
Copy link
Contributor

App 上的基础组件现在是不会渲染的,也就是说下面的 View 是不会渲染到页面上的。

class App extends React.Component {
  render() {
    return (
     <View id="app">
        {this.props.children}
      </View>
    );
  }
}

这样的写法会让开发者感到困惑,明明是个 React 组件,但是不能真正渲染。 Taro 的 app 文件就是这么写的。

是不是可以改成在 App 里提供 injectProviders 的方式,而不是 React 组件

其实不止 taro 这样,其他的框架也是类似的,App 里面是不渲染的,我觉得不用改这样就挺好

@yesmeck yesmeck force-pushed the one-react-instance branch 2 times, most recently from 902e73f to 68c3179 Compare August 31, 2019 16:39
@yesmeck yesmeck changed the title [WIP]在 App 上创建 React 实例 在 App 上创建 React 实例 Aug 31, 2019
@malash
Copy link

malash commented Sep 1, 2019

@Pochodaydayup 你说Taro和其他框架也有类似的处理方式,有文档或者链接可以看一下吗?

@malash
Copy link

malash commented Sep 1, 2019

我认为依赖 getCurrentPages不是一个好的实现方式。首先这个API并不稳定,它在各个平台下有差异;其次如果考虑支持将React组件导出成小程序自定义组件,可能会带来处理的麻烦。

我个人对在App上创建React实例的需求持保留态度。

cc @jimexist @byunicorn

@yesmeck yesmeck force-pushed the one-react-instance branch 6 times, most recently from 61eb9f8 to e0ac1c7 Compare September 1, 2019 15:35
@yesmeck yesmeck merged commit 8bf93e3 into develop Sep 2, 2019
@yesmeck yesmeck deleted the one-react-instance branch September 2, 2019 03:48
console.log('onShow', options);
}

return() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是 render () , 不是 return () 吧

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💣

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants