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

关于子组件componentWillReceiveProps不执行的问题 #1640

Closed
patchBig opened this issue Dec 22, 2018 · 9 comments
Closed

关于子组件componentWillReceiveProps不执行的问题 #1640

patchBig opened this issue Dec 22, 2018 · 9 comments
Assignees

Comments

@patchBig
Copy link

父组件:

// father.js
import Taro, { Component } from '@tarojs/taro';
import { View, Image, Text, Input, Button } from '@tarojs/components';
import Son from '../son/son'

export default class Test extends Component {
     constructor(props) {
         super(props);
      }
     componentWillMount() {
         console.log("page componentDidMount")
         setTimeout(() => {
            this.setState({
                showToast: true
            }, 6000)
         })
     }
      render() {
           let { show } = this.state;
           return (
              <Son show={showToast} 
          )
      }
}

子组件

import { Block, View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import withWeapp from '@tarojs/with-weapp'
import Classnames from 'classnames'

import './index.scss'

@withWeapp('Component')
class _C extends Taro.Component {
  constructor(props) {
    super(props)
  }

  static defaultProps = {
    show: false,
    title: '请重试',
    time: 2000
  }

  componentWillReceiveProps(props){
    console.log("componentWillReceiveProps");
    console.log(props);
  }
  
  hideToast = duration => {
    clearTimeout(this.timer || null)
    this.delay(duration).then(() => {
      this.setState({
        showToast: false
      })
    })
  }
  delay = time => {
    return new Promise(resolve => {
      this.timer = setTimeout(() => {
        resolve()
      }, time)
    })
  }

  config = {
    component: true
  }

  render() {
    let { show, title, time } = this.props
    const { showToast } = this.state
    
    if(typeof showToast === 'boolean') {
      show = showToast
    }

    if(show) {
      this.hideToast(time)
    }

    return (
      <View 
        className={Classnames({
          'toast toast_basic': true,
          show: show
        })}
      >
        {title}
      </View>
    )
  }

  componentDidMount() {
    console.log("componentDidMount")
  }
}

export default _C
@taro-bot
Copy link

taro-bot bot commented Dec 22, 2018

欢迎提交 Issue~

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

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

Good luck and happy coding~

@taro-bot
Copy link

taro-bot bot commented Dec 23, 2018

CC @Chen-jj

@Chen-jj
Copy link
Contributor

Chen-jj commented Dec 24, 2018

@patchBig 老哥你检查一下你父组件的代码吧,两个大问题,setTimeout 、 show 和 showToast,编码前打开一下 ESLint 吧。

@taro-bot
Copy link

taro-bot bot commented Dec 24, 2018

Hello~

您的问题我们无法复现。如果有空的话还请拔冗提供一个简单的复现 demo,否则这个 issue 将在 15 天后被自动关闭。

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

Good luck and happy coding~

@FaureWu
Copy link

FaureWu commented Dec 24, 2018

复现代码地址: https://github.com/FaureWu/weapp-clover
项目启动命令:yarn && yarn mock:weapp

项目启动由于没有配置阿里云,会报错,可忽略
项目启动后,我在复现代码中打印了相关日志

// components/home/carousel/carousel.js

  componentWillReceiveProps(nextProps) {
    const { banners } = nextProps
    console.log('componentWillReceiveProps', banners)
    let showBanners = banners
    if (banners.length === 2) {
      showBanners = banners.concat(
        banners.map(banner => ({
          backup: true,
          ...banner,
        })),
      )
    }

    this.setState({ showBanners })
  }

  render() {
    const { banners } = this.props
    const { showBanners, currentDotIndex } = this.state

    const previousMargin =
      showBanners.length <= 1 ? Taro.pxTransform(48) : Taro.pxTransform(24)
    const nextMargin = Taro.pxTransform(48)

    console.log('render', banners)
 }

在render中打印可以发现,banners实际由两个变成三个,但是componentWillReceiveProps并无任何打印信息

注意:让这个bug消失的办法是修改server/routes/mock.js代码

Object.keys(mocks).forEach(route => {
  const [method, url] = route.split(' ')

  if (validMethods.indexOf(method) !== -1 && url) {
    router[method.toLocaleLowerCase()](url, (req, res, next) =>
     // 修改这个模拟网络请求延时时间为1到2秒,改bug就不存在了
      delay(1).then(() => mocks[route](req, res, next)),
    )
  } else {
    throw Error(`invalid request [${route}]`)
  }
})

@Chen-jj
Copy link
Contributor

Chen-jj commented Dec 25, 2018

@FaureWu 发一下父组件的代码,同时最好精简出父子组件的可运行代码,这样可以更好地复现问题,节省你我的时间。

@FaureWu
Copy link

FaureWu commented Dec 25, 2018

@Chen-jj 我调试了发现,未触发原因是,因为数据改变过快,组件还未装载完成,数据已经更新了,因此未调用componentWillReceiveProps

Taro文档中有个说明:在装载期间,Taro 并不会调用带有初始属性的 componentWillReceiveProps方法。调用 this.setState 通常不会触发componentWillReceiveProps。

这也许不算个bug

@Chen-jj
Copy link
Contributor

Chen-jj commented Dec 25, 2018

@FaureWu 初次渲染不会触发 componentWillReceiveProps。小程序页面或组件 Ready 后 props 改变才会触发。

@patchBig
Copy link
Author

@Chen-jj 我调试了发现,未触发原因是,因为数据改变过快,组件还未装载完成,数据已经更新了,因此未调用componentWillReceiveProps

Taro文档中有个说明:在装载期间,Taro 并不会调用带有初始属性的 componentWillReceiveProps方法。调用 this.setState 通常不会触发componentWillReceiveProps。

这也许不算个bug

我遇到的应该是和你一样,然后你现在打算手动加延时解决吗?

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

4 participants