我正在构建一个测验,从数据数组中随机 Select 20个项目.每个测验问题播放一段带有柔道技术的视频,参赛者试图识别所示的技术.一旦答案被点击(对或错),它就会计算分数,然后转到下一个视频.

PROBLEM-即使它应该在props 中使用,它也不能在装载状态下使用.奇怪的是,视频会在游戏结束后自动播放,你可以再次点击播放.当我加载屏幕并手动播放时,如果我暂停它,我会注意到测验中的下一个项目加载了下一个视频,但它从我暂停前一个视频的位置开始播放--这让我完全迷惑了.

SOLUTION-本质上,每个问题从头开始自动播放.我对原住民的react 有点新手,但我相信你们中的一些人可能会觉得这是一个相当愚蠢的问题,呵呵

我感谢你的帮助

import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View } from 'react-native'
import * as Progress from 'react-native-progress';
import theme from '../assets/theme'
import CustomButton from './CustomButton';
import { Video } from 'expo-av';

const VideoPlay = ({data, shouldPlay}) => {
  return (
    <View style={styles.videoitems}>
      <Video
        source={{ uri: `https://judopedia.wiki/assets/videos/${data}` }}
        resizeMode="contain"
        shouldPlay={shouldPlay}
        style={styles.video}
        useNativeControls
      />
    </View>
  )
}


const VideoTriviaGame = ({data}) => {
  const [currentQuestion, setCurrentQuestion] = useState(0)
  const [score, setScore] = useState(0)
  const [showScore, setShowScore] = useState(false)
  const [quizData, setQuizData] = useState([]);
  const [progress, setProgress] = useState(0);

  useEffect(() => {
    const random = [...data].sort(() => Math.random()).slice(0, 20);
    setQuizData(random);
  }, [])

  const handleAnswer = (selectedAnswer) => {
    const answer = quizData[currentQuestion]?.answer;

    if(answer === selectedAnswer){
      setScore((prevScore)=> prevScore + 1)
    }

    handleNextQuestion()
  }

  const handleNextQuestion = () => {
    const nextQuestion = currentQuestion + 1;
    if(nextQuestion < quizData.length){
      setCurrentQuestion(nextQuestion)
      if (progress < quizData.length - 1) {
        setProgress(progress + .05);
      }
    } else {
      setShowScore(true)
    }
  }

  const handleRestart = () => {
    setCurrentQuestion(0)
    setScore(0)
    setShowScore(false)
    setProgress(0);
  }

  return (
    <View style={{flex:1}}>
      {showScore 
        ? null
        : <VideoPlay data={quizData[currentQuestion]?.url} shouldPlay/>
      }
      {showScore 
        ? 
          <View style={styles.gamecnt}>
            <View style={{flex:1, alignItems:"center", justifyContent:"center", width:"100%"}}>
              <Text style={{color: theme.colors.white, fontSize:24, textAlign:"center", marginBottom:10}}>
                You scored {score} out of {quizData.length}
              </Text>

              <View style={styles.btnGroup}>
                <CustomButton text="Play Again" primary onPress={handleRestart}/>                
              </View>
            </View>
            
          </View>
        :           
          <View style={styles.gamecnt}>
            <View style={{display:"flex", alignItems:"center"}}>
              <Text style={styles.counter}> 
                {Math.round(progress * 20) + 1 } of {quizData.length}
              </Text>
              <Progress.Bar 
                progress={progress+0.05} 
                width={300} 
                animated={true}
                unfilledColor={theme.colors.darkgray}
                color={theme.colors.primaryend}
                height={8} 
                borderWidth={0} />
            </View>
            <View style={styles.btnGroup}>
              {quizData[currentQuestion]?.options.map((item, index) => (                
                <CustomButton 
                  key={index}
                  onPress={() => handleAnswer(item)}
                  text={item} primary 
                />
              ))}
            </View>
          </View>          
      }        
    </View>
  )
}

export default VideoTriviaGame

const styles = StyleSheet.create({  
  counter:{
    color: theme.colors.white, 
    fontSize:18, 
    fontWeight:"bold",
  },
  gamecnt:{
    flex:1, 
    alignItems:"center", 
    justifyContent:"start",
  },
  btnGroup:{
    width:"100%",
  },
  videoitems: {
    flex: 1,
    width: '100%',
    backgroundColor: '#000',
    alignItems: 'center',
    justifyContent: 'center',
  },
  video: {
    width: '100%',
    height: '100%',
  }
})

推荐答案

在渲染期间,Video组件状态保持不变,包括positionMillisisPlaying,即使您更改视频链接也是如此.

要重置视频,请执行以下操作:

  • 一种方法是向Video添加一个密钥,该密钥随每个新项而变化 链接.
  • 另一种方法是通过回调或onPress事件重新启动视频.它是 可通过React.useRefsetStatusAsync和加法实现 ref={videoRef}Video个组件

关于开始时的shouldPlay分.我用gamecnt部分的一半复制了你的代码,它工作得很好.这可能是原始代码的一些其他潜在问题,例如,在组件中将shoulPlay设置为null.

Restart Video on link change:

<Video
  key={data} // this will reset video state, every time data changes

  source={{ uri: `https://judopedia.wiki/assets/videos/${data}` }}
  resizeMode="contain"
  shouldPlay={shouldPlay}
  style={styles.video}
  useNativeControls
/>

Restart Video onPress:

import React from "react";
import { View, Button, SafeAreaView, StatusBar } from "react-native";
import { Video } from "expo-av";

export default function App() {
  const videoRef = React.useRef(null);

  return (
    <SafeAreaView style={{ flex: 1, paddingTop: StatusBar.currentHeight }}>
      <Button
        title={"Restart"}
        onPress={() =>
          videoRef.current.setStatusAsync({ shouldPlay: true, positionMillis: 0 })
        }
      />

      <View style={{ flex: 1, width: "100%" }}>
        <Video
          ref={videoRef}
          style={{ width: "100%", height: "100%" }}
          source={{ uri: "https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4"}}
          resizeMode="contain"
          useNativeControls
        />
      </View>
    </SafeAreaView>
  );
}

Javascript相关问答推荐

通过使用100%间隔时间来代表我们还剩多少时间来倒计时

我应该在redux reducer中调用其他reducer函数吗?

我开始使用/url?q=使用Cheerio

浮动Div的淡出模糊效果

你怎么看啦啦队的回应?

如何通过使用vanilla JS限制字体大小增加或减少两次来改变字体大小

如何解决useState错误—setSelect Image不是函数''

VUE 3捕获错误并呈现另一个组件

正则表达式,允许我匹配除已定义的子字符串之外的所有内容

检索相加到点的子项

JavaScript是否有多个`unfined`?

如何限制显示在分页中的可见页面的数量

为什么当我更新数据库时,我的所有组件都重新呈现?

当从其他文件创建类实例时,为什么工作线程不工作?

使用jQuery find()获取元素的属性

如何在FiRestore中的事务中使用getCountFromServer

如何向内部有文本输入字段的HTML表添加行?

如何使用fltter_js将对象作为参数传递给javascrip?

如何在不将整个文件加载到内存的情况下,在Node.js中实现Unix粘贴命令?

MUI-TABLE:MUI表组件中交替行的不同 colored颜色 不起作用