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

小程序 高阶组件当中使用mobx获取不了props #1313

Closed
tp-life opened this issue Nov 30, 2018 · 13 comments
Closed

小程序 高阶组件当中使用mobx获取不了props #1313

tp-life opened this issue Nov 30, 2018 · 13 comments
Assignees

Comments

@tp-life
Copy link

tp-life commented Nov 30, 2018

问题描述
更新到1.2.0-beta.6 时使用高阶组件,在高阶组件当中使用mobx @Inject时丢失props。在1.2.0-beta.4时该问题不存在。。

复现步骤

// login 装饰器
import Taro from '@tarojs/taro'
import { inject } from '@tarojs/mobx'
import { User } from '../store/user'

interface DecoProps {
    user: User
}

// 支持的生命周期
const LIFE_CYCLE_MAP =[ 'willMount', 'didMount', 'didShow' ];

export default function weappLogin (lifecycle: string = 'willMount') {
    if (!LIFE_CYCLE_MAP.includes(lifecycle)) {
        return component => component
    }
    return function withLogin(component) {

        @inject('user')
        class withLoginComponent extends component<DecoProps, any> {
            async componentWillMount() {
                if (super.componentWillMount && lifecycle === LIFE_CYCLE_MAP[0]) {
                    const res = await this.autoLogin()
                    if (!res) return
                } 

                super.componentWillMount && super.componentWillMount()
            }

            async componentDidMount() {
                if (super.componentDidMount && lifecycle === LIFE_CYCLE_MAP[1]) {
                    const res = await this.autoLogin()
                    if (!res) return
                    
                }  
                super.componentDidMount && super.componentDidMount()
            }

            async componentDidShow() {
                if (super.componentDidShow && lifecycle === LIFE_CYCLE_MAP[2]) {
                    const res = await this.autoLogin()
                    if (!res) return
                    
                } 
                super.componentDidShow &&  super.componentDidShow()
            }


            async autoLogin () {
              // 此处console.log(this.props) 输出空对象{}
          
                if (this.props.user.jwt) {    
                    return true;    
                }
                await this.props.user.login()
                if (this.props.user.jwt) {
                    return true;
                }
                Taro.showModal({title: '登录提醒', content: '当前操作需要登录后继续使用',confirmText: '前往登录', showCancel: false}).then(() => {
                    Taro.navigateTo({url: '/pages/login/index'})
                })
                return false
            }

            render() {
                super.render();
            }
        }
        return withLoginComponent
    } 
}


// index page

interface defaultProps {
  wxlogin: Wxlogin
}

@share({
  title: '首页啦'
})
@login()
@inject('wxlogin')
@observer
export default class Index extends Component<defaultProps, {} > {}

期望行为
希望能正常获取通过@Inject 注入到props当中

报错信息

[这里请贴上你的完整报错截图或文字]

image
系统信息

  • 操作系统: mac 10.14
  • Taro 版本 1.2.0-beta.6
  • Node.js 版本 v11.3.0
  • 报错平台 weapp

补充信息

@taro-bot
Copy link

taro-bot bot commented Nov 30, 2018

欢迎提交 Issue~

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

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

Good luck and happy coding~

@nanjingboy
Copy link
Member

@wokill store/user 这个代码还方便贴出来吗?

@tp-life
Copy link
Author

tp-life commented Dec 3, 2018

import Taro from '@tarojs/taro'
import { observable, flow, configure, action  } from 'mobx'
import { GetData, SetData, JWT, JWTEXPIRE } from '../utils/storage' // 缓存信息
import { UserInfo } from '../interfaces/user'
import delay from '../utils/delay'

// 设定数据只能在action 中改变
configure({ enforceActions: 'observed' })

interface register {
    phone: string,
    yzm: string,
    [key: string]: any
}

export class User {
    @observable userInfo: UserInfo
    @observable uuid: string = ''
    @observable jwt: string = GetData(JWT) || ''

    login = flow(function * () {
        // TODO:: 增加延时,测试代码,开发需替换
        yield Taro.request({url: 'https://www.baidu.com'}) 
        console.log('88888')
        SetData(JWT, 'jwt', JWTEXPIRE)
        this.jwt = 'jwt'
    })

    register = flow(function * (regData: register) {
        console.log(regData)
        this.uuid = '456'
    })

    @action
    sendSms(phone: string) {
        // 
    } 
}

export default new User()

store/user 代码如上,发现属性装饰器好像可以用了。。

@nanjingboy
Copy link
Member

@wokill 无法复现,能把你的demo完整代码给发一下吗?[email protected]

@tp-life
Copy link
Author

tp-life commented Dec 5, 2018

@nanjingboy 又尝试了几次,发现在组件componentWillMount声明周期当中获取不到props,在componentDidMount生命周期当中就可以正确的获取到props了。这是什么原因呢?是因为是异步注入还是是在组件挂载之后再进行注入的?同时尝试了一下之前的版本,在componentWillMount生命周期中可以正确的获取到该props.

@nanjingboy
Copy link
Member

@wokill 你能把完整的demo发到我的邮箱吗?这样方便快速定位问题

@tp-life
Copy link
Author

tp-life commented Dec 5, 2018

已发送到你的邮箱里面了,请注意查收一下

@nanjingboy
Copy link
Member

@wokill 已修复,等官方发布新版本后你可以再试下

@tp-life
Copy link
Author

tp-life commented Dec 5, 2018

嗯,非常感谢

@tp-life
Copy link
Author

tp-life commented Dec 7, 2018

另外再咨询一个相关的问题,该问题只发生在componentWillMount生命周期内:
同样是该login高阶组件,因为在componentWillMount生命周期当中使用了async/await,调用super.componentWillMount()async/await之后。这样导致在使用该高阶组件的page中的mobx观察对象中的数据即使发生了改变,UI层也不会重新渲染,这是什么问题?
代码如下:

// login
export default function weappLogin (lifecycle: string = 'willMount') {
    if (!LIFE_CYCLE_MAP.includes(lifecycle)) {
        return component => component
    }
    return function withLogin(component) {
        @inject('user')
        class withLoginComponent extends component {
            //TODO:: componentWillMount 当中使用了await 导致外层mobx观察数据发生改变,ui层不重新渲染。该问题只发生在 componentWillMount生命周期中
            async componentWillMount() {
                if (super.componentWillMount && lifecycle === LIFE_CYCLE_MAP[0]) {
                    //TODO:: 此处使用了 await  去除掉await无异常。
                    const res = await this.autoLogin()
                    if (!res) return
                } 

                super.componentWillMount && super.componentWillMount()
            }

            async componentDidMount() {
                if (super.componentDidMount && lifecycle === LIFE_CYCLE_MAP[1]) {
                    const res = await this.autoLogin()
                    if (!res) return
                    
                }  
                super.componentDidMount && super.componentDidMount()
            }

            async componentDidShow() {
                if (super.componentDidShow && lifecycle === LIFE_CYCLE_MAP[2]) {
                    const res = await this.autoLogin()
                    if (!res) return
                    
                } 
                super.componentDidShow &&  super.componentDidShow()
            }


            async autoLogin () {
                const { user } = this.props
                if (user.jwt) {    
                    return true;    
                }
                await user.login()
                if (user.jwt) {
                    return true;
                }
                Taro.showModal({title: '登录提醒', content: '当前操作需要登录后继续使用',confirmText: '前往登录', showCancel: false}).then(() => {
                    Taro.navigateTo({url: '/pages/login/index'})
                })
                return false
            }

            render() {
                super.render();
            }
        }
        return withLoginComponent
    } 
}

使用login.js的pages:

// home/index.js
import Taro, { Component,Config } from '@tarojs/taro'
import { View, Image, Text } from '@tarojs/components'
import { observer, inject } from '@tarojs/mobx'
import { AtIcon } from 'taro-ui'
import { share, login } from '../../decorator'
import { User } from '../../store/declare'
import './index.scss'

interface HomeProps { 
    user: User
}


@share()
@login()
@inject('user')
@observer
export default class Home extends Component<HomeProps, {}> {

    static defaultProps = {} as HomeProps

    config: Config = {
        navigationBarTitleText: '我的'
    }

    constructor(props) {
        super(props);
    }

    componentWillMount() {
        const { user } = this.props
        // TODO::加载用户详情数据, 此处加载完用户数据之后,改边userInfo后,该页面并不会重新渲染
        user.loadInfo()
    }

    componentDidMount() {
        
    }

    navigateTo(url: string) {
        Taro.navigateTo({
            url: url
        })
    }
    
    // 提现
    onBalance() {
        const {user: { balance}} = this.props
        if ( balance < 0  ) {
            Taro.showToast({
                title: '暂时没有可提现金额',
                icon: 'none'
            })
            return
        }
        this.navigateTo('/pages/capital/balance')
    }

    render() {
        const {user: {userInfo: {nickName, avatarUrl, phone}, frozen, cashed, balance}} = this.props
        console.log(nickName,balance);
        return (
            <View className='home_container'>
                
            </View>
        );
    }
}
// user.js    mobx
import Taro from '@tarojs/taro'
import { observable, flow, configure, action  } from 'mobx'
import { GetData, SetData, JWT, JWTEXPIRE } from '../utils/storage' // 缓存信息
import { UserInfo, PushEl, ReceEl } from '../interfaces/user'
import delay from '../utils/delay'

// 设定数据只能在action 中改变
configure({ enforceActions: 'observed' })

interface register {
    phone: string,
    yzm: string,
    [key: string]: any
}

const user = { 
    name: '章三',
    phone: '18080093730',
    nickName: '飞象',
    city: '成都',
    sign: '才不要些什么签名',
    balance: 500,
    cashed: 1000.50,
    frozen: 268.36,
    avatarUrl: 'http://storage.360buyimg.com/mtd/home/32443566_635798770100444_2113947400891531264_n1533825816008.jpg'
}


class User {
     
    @observable uuid: string = ''
    @observable jwt: string = GetData(JWT) || ''
    @observable balance: number = 0
    @observable cashed: number = 0
    @observable frozen: number = 0
    @observable userInfo: UserInfo
    
    constructor() {
        this.userInfo = {} as UserInfo
    }

    // 登录
    login = flow(function * () {
        // TODO:: 增加延时,测试代码,开发需替换
        yield Taro.request({url: 'https://www.baidu.com'}) 
        console.log('88888')
        SetData(JWT, 'jwt', JWTEXPIRE)
        this.jwt = 'jwt'
    })

    // 用户信息
    loadInfo = flow(function * () {
        const { balance, cashed, frozen } = user
        this.cashed = cashed
        this.balance = balance
        this.frozen = frozen
        this.userInfo = user
        console.log(this.balance)
    })



    // 注册
    register = flow(function * (regData: register) {
        console.log(regData)
        this.uuid = '456'
    })

    // 更新用户数据
    updateData = flow(function * (attr: string, value: string) {
        let info = this.userInfo
        if (info.hasOwnProperty(attr)) {
            // TODO:: 缺少发起更改请求
            info[attr] = value
            this.userInfo = Object.assign({}, this.userInfo, info)
            return true
        }
        return false
    })

    // 修改手机号码
    updatePhone = flow(function * (phone:string, code: string) {
        //TODO:: 修改手机号码
        return true
    })

    // 提现申请
    sendCashed = flow(function *() {
        // 更新userInfo 金额
        return true
    })

    // 发送验证码
    @action
    sendSms(phone: string) {
        // 
    }

    

}

export default new User()

@nanjingboy
Copy link
Member

@wokill 那这个问题跟这个issue无关了,把你的demo发给我,有空看下。

@tp-life
Copy link
Author

tp-life commented Dec 7, 2018

OK,我重发一份到你邮箱,我新开一个issue

@tp-life tp-life closed this as completed Dec 7, 2018
@nanjingboy
Copy link
Member

@wokill ok,有空的话我看一下

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

3 participants