Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

小程序中使用装饰器,报没有_createData错误, h5端正常 #5009

Closed
waveheart opened this issue Dec 5, 2019 · 9 comments
Closed
Assignees

Comments

@waveheart
Copy link

waveheart commented Dec 5, 2019

问题描述

尝试在小程序中写自定义的装饰器,本来是想对获取列表的东西封装一下,但是发现我以前写装饰器的方式在小程序中报错,但是在h5端正常

复现步骤

新建 index.jsx , testDecarator.js
2.
正常使用@装饰
3.
小程序端报错,装饰器无效,h5端正常

image

image

index.jsx

import Taro, { Component } from "@tarojs/taro";
import { View, Text } from "@tarojs/components";
import testDecorator from "./testDecorator";

@testDecorator
class TestPage extends Component {
  constructor(props) {
    super(props);
  }

  state = {};

  render() {
    return (
      <View>
        <Text>test page</Text>
        <Text>装饰器添加的属性---{this.props.test}</Text>
      </View>
    );
  }
}

export default TestPage;

testDecorateor.js

import Taro, { Component } from "@tarojs/taro";
import { View, Text } from "@tarojs/components";

const testDecorator = Comp =>
  class extends Component {
    constructor(props) {
      super(props);
    }

    state = {};

    render() {
      return (
        <View>
          <Text>装饰器添加的</Text>
          <Comp test='test_111111'></Comp>
        </View>
      );
    }
  };

export default testDecorator;


期望行为

小程序端正常使用装饰器

报错信息

VM1827:1 TypeError: componentInstance._createData is not a function
    at Object.createComponent (index.js:2585)
    at index.js:70
    at require (VM1843 WAService.js:1)
    at <anonymous>:251:7
    at HTMLScriptElement.scriptLoaded (appservice?t=1575516412005:2929)
    at HTMLScriptElement.script.onload (appservice?t=1575516412005:2941)
console.warn @ VM1827:1
createComponent @ index.js:2593
(anonymous) @ index.js:70
require @ VM1843 WAService.js:1
(anonymous) @ VM1941:251
scriptLoaded @ appservice?t=1575516412005:2929
script.onload @ appservice?t=1575516412005:2941
load (async)
(anonymous) @ appservice?t=1575516412005:2940
(anonymous) @ appservice?t=1575516412005:2993

系统信息

Taro CLI 1.3.25 environment info:
System:
OS: Windows 10
Binaries:
Node: 10.15.0 - C:\Program Files\nodejs\node.EXE
Yarn: C:\Users\Administrator\Documents\react\myApp>"node" "C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\bin\yarn.js" -v
1.17.3 - ~\AppData\Roaming\npm\yarn.CMD
npm: 6.4.1 - C:\Program Files\nodejs\npm.CMD

补充信息

我的装饰器使用的不对么???但是在h5端一切正常啊

更新

有没有一个Taro装饰器的demo给看一下?

@taro-bot
Copy link

taro-bot bot commented Dec 5, 2019

CC @Chen-jj

@taro-bot
Copy link

taro-bot bot commented Dec 5, 2019

欢迎提交 Issue~

如果你提交的是 bug 报告,请务必遵循 Issue 模板的规范,尽量用简洁的语言描述你的问题,最好能提供一个稳定简单的复现。🙏🙏🙏

如果你的信息提供过于模糊或不足,或者已经其他 issue 已经存在相关内容,你的 issue 有可能会被关闭。

Good luck and happy coding~

@waveheart
Copy link
Author

PS 我都 写state 为啥给我 warning 说我没写state??

@shenghanqin
Copy link
Collaborator

第一种尝试

import Taro, { Component } from "@tarojs/taro";
import { View, Text } from "@tarojs/components";
import testDecorator from "./testDecorator";

@testDecorator
class TestPage extends Component {
  constructor(props) {
    super(props);
    this.state = {}; // 写在这里试试看?
  }

  render() {
    return (
      <View>
        <Text>test page</Text>
        <Text>装饰器添加的属性---{this.props.test}</Text>
      </View>
    );
  }
}

export default TestPage;

第二个细节

在testDecorateor.js里面,不要出现
constructor和this.state的预定义

import Taro, { Component } from "@tarojs/taro";
import { View, Text } from "@tarojs/components";

const testDecorator = Comp =>
  class extends Component {

    render() {
      return (
        <View>
          <Text>装饰器添加的</Text>
          <Comp test='test_111111'></Comp>
        </View>
      );
    }
  };

export default testDecorator;

第三个细节

你可以看看我这里写的,

export default function WithPage(TaroComponent) {
  class CorePage extends TaroComponent {
    static options = {
      addGlobalClass: true
    }
    componentWillMount() {
    // TODO 这里写代码
      
      if (super.componentWillMount) {
        super.componentWillMount()
      }
    }



  }
  CorePage.displayName = TaroComponent.displayName
    || TaroComponent.name
    || 'CorePage'

  return CorePage
}

@taro-bot
Copy link

taro-bot bot commented Dec 6, 2019

Hello~

您的问题楼上已经有了确切的回答,如果没有更多的问题这个 issue 将在 15 天后被自动关闭。

如果您在这 15 天中更新更多信息自动关闭的流程会自动取消,如有其他问题也可以发起新的 Issue。

Good luck and happy coding~

@waveheart
Copy link
Author

waveheart commented Dec 6, 2019

@shenghanqin

发现导致报_createdata错误的原因是,我继承的是 taro中的component。
你的方法继承的是原有的component类,但是冒昧的问一句, react 官方不是不建议任何继承式的写法么?既然用了装饰器,为什么还要继承?
实际上在用你的方法以后,虽然不报错,但是无法向被装饰的组件传递东西


import Taro from "@tarojs/taro";
import { View, Text } from "@tarojs/components";

export default function WithPage(TaroComponent) {
  class CorePage extends TaroComponent {
    static options = {
      addGlobalClass: true
    };
    componentWillMount() {
      // TODO 这里写代码

      if (super.componentWillMount) {
        super.componentWillMount();
      }
    }

    render() {
      return (
        <View>
          <Text>想添加点东西添不上</Text>
          <TaroComponent></TaroComponent>
        </View>
      );
    }
  }
  CorePage.displayName =
    TaroComponent.displayName || TaroComponent.name || "CorePage";

  return CorePage;
}

@Chen-jj
Copy link
Contributor

Chen-jj commented Jan 6, 2020

@waveheart 目前高阶函数不能劫持 render 方法。render 会在编译时被识别出来编译成 createData 函数,HOC 里的 render 编译器识别不出来,因此会有问题。

@plimerence
Copy link

同样的问题 ,导致问题就是h5实现的装饰器 完全没有办法用到小程序

@TokeyJerry
Copy link

@shenghanqin 能帮忙解释下您说的

第二个细节
在testDecorateor.js里面,不要出现
constructor和this.state的预定义
” 这个是出于什么原因不可以扩展么?我有个需求是想在每个页面预设置 一个 state 值(因为:1、每个业务页面其实不一定都关心这个值;2、即使关心,也不想每个页面都写一遍),所以有更好的处理方式么?

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

No branches or pull requests

5 participants