remaxjs / remax

使用真正的 React 构建跨平台小程序
https://remaxjs.github.io/remax/
MIT License
4.57k stars 364 forks source link

[问题] #1940

Closed Resolution666 closed 2 years ago

Resolution666 commented 2 years ago

问题描述 在使用remax写函数组件时,我在父组件中条件渲染子组件,当满足条件的子组件渲染时,在子组件中使用usePageEvent监听子组件的onShow, onReady, onLoad 等生命周期均不执行,只有 react 中提供的useEffect 执行了

示例代码 父组件 `import React, { useState, useCallback, useEffect } from 'react' import { View, Text } from 'remax/wechat' import StepOne from './StepOne'; import StepTwo from './StepTwo'; interface IProps {

}

interface IState { step: number }

const LiveDetection:React.FC = () => { const [ step, setStep ] = useState(0)

const nextStep = useCallback(() => {
    setStep(step => step + 1)
}, [step])

const resetStep = useCallback(() => {
    setStep(0)
}, [])

useEffect(() => {
    return () => {
        console.log('unmout')
        resetStep()
    }
}, [])

return (
    <View>
        {
            step === 0  && <StepOne nextStep={nextStep} />
        }
        {
            step === 1  && <StepTwo />
        }
    </View>
)

}

export default LiveDetection 子组件 import * as React from 'react'; import { View, Button, Camera, createCameraContext, Text, Video, VideoProps } from 'remax/wechat'; import { usePageEvent } from 'remax/macro' import { styled } from 'linaria/react'

const BlackTip = styled(View) margin-top: 30; margin-bottom: 50; display: flex; flex-flow: column;

const BlackTipTxt = styled(View) font-size: 30px; text-align: center;

const BlackTipTxtNumber = styled(View) font-size: 100px; text-align: center; margin-top: 30px;

const CameraContent = styled(View) display: flex; justify-content: center; position: relative; margin-top: 40px;

const CameraContentText = styled(View) display: flex; justify-content: center; flex-flow: column; align-items: center; position: absolute; z-index: 100; font-weight: bold; font-size: 18px; color: #fff; margin-top: 50px;

const CameraContainer = styled(Camera) height: 450px; width: 450px; clip-path: circle(50% at 50% 50%);

const VideoContent = styled(View) display: flex; align-items: center; justify-content: center; margin-top: 50px;

const VideoContainer = styled(Video) height: 450px; width: 450px; border-radius: 50%; display: flex;

const ButtonContent = styled(View) text-align: center; box-sizing: border-box; padding-left: 12px; padding-right: 12px; margin-top: 60px;

const StopButton = styled(Button) border: 1px solid #ff934a; color: #ff934a; background-color: #fff;

const EndButton = styled(Button) border: 1px solid #ff934a; color: #fff; background-color: #ff934a;

const ReScanButton = styled(Button) border: none; color: #ff934a; background-color: #fff;

interface IProps { }

enum EMVideoStatus { INIT = 'init', ONGOING = 'ongoing', END = 'end', }

const mapConfirmTxt = {

[EMVideoStatus.ONGOING]: '结束拍摄',
[EMVideoStatus.END]: '使用视频',

}

const StepTwo:React.FC = () => { // 创建相机上下文对象 const cameraContext = React.useRef(); cameraContext.current = createCameraContext() // 创建定时器具柄 const timer = React.useRef(); // 页面当前状态 const [ status, setStatus ] = React.useState(EMVideoStatus.INIT) // 相机是否 ready const [ ready, setReady ] = React.useState(false) // 倒计时参数 const [ countingNum, setCountingNum ] = React.useState(5) // 视频对象 const [ viderObj, setVideoObj ] = React.useState()

usePageEvent('onReady', () => { console.log('onReady =====>') })

// React.useEffect(() => { // // 绑定相机上下文对象 // cameraContext.current?.startRecord({ // success:function (res) { // console.log('startRecord=====> ', res) // } // }) // }, [])

React.useEffect(() => { if(!ready){ // 监听ready状态, 当ready为 false 时,设置定时器,执行倒计时 timer.current = setInterval(() => { setCountingNum((state) => state - 1) }, 1000) } return () => { clearInterval(timer.current) } }, [ready])

React.useEffect(() => { if(countingNum === 0 && !ready){ // 倒计时结束,改变ready状态,清除定时器,设置当前status clearInterval(timer.current) setReady(true) setStatus(EMVideoStatus.ONGOING) cameraContext.current?.startRecord({ success:function (res) { console.log('startRecord=====> ', res) } }) } }, [countingNum])

// 初始化相机参数 const initCamera = () => { setVideoObj({ src: '' }); setReady(false); setCountingNum(5) setStatus(EMVideoStatus.INIT) }

// 开始录像 const handleStartRecord = async () => { console.log(cameraContext) initCamera() }

// 结束录像 const handleStopRecord = () => { console.log(cameraContext.current) cameraContext.current?.stopRecord({ success: function (res) { console.log('stopRecord=====> ', res) setStatus(EMVideoStatus.END) setVideoObj({ src: res.tempVideoPath}) }, fail: function (error) { console.log(error) } }) }

// 摄像头在非正常终止时触发 const eventStop = () => {

} // 用户不允许使用摄像头时触发
const eventError = () => {

} // 相机初始化完成时触发 const eventInitDone = () => {

} return ( <>

请确保正脸水平对准屏幕摄像区 先眨眨眼,再张张嘴 { status !== EMVideoStatus.END ? ( { countingNum !== 0 ? ( <> 拍摄倒计时 {countingNum} ) : ( 先眨眨眼,再张张嘴 ) } { } ) : ( ) } { status === EMVideoStatus.ONGOING && {mapConfirmTxt.ongoing} } { status === EMVideoStatus.END && {mapConfirmTxt.end} } { status === EMVideoStatus.END &&重新拍摄 } ); }; export default StepTwo `