React native 为什么我的象棋时钟不更新视图?
我想看看我是否可以为我的游戏组制作一个有多个玩家的象棋时钟应用程序,但是我在间隔倒计时时更新我的视图时遇到了问题 我真的不知道为什么它在react native中不起作用,任何帮助都将不胜感激 我的代码在下面React native 为什么我的象棋时钟不更新视图?,react-native,react-hooks,setinterval,React Native,React Hooks,Setinterval,我想看看我是否可以为我的游戏组制作一个有多个玩家的象棋时钟应用程序,但是我在间隔倒计时时更新我的视图时遇到了问题 我真的不知道为什么它在react native中不起作用,任何帮助都将不胜感激 我的代码在下面 import React, {useState, useEffect} from 'react'; import {ScrollView, View, Text, TouchableOpacity} from 'react-native'; import {GlobalStyles} fr
import React, {useState, useEffect} from 'react';
import {ScrollView, View, Text, TouchableOpacity} from 'react-native';
import {GlobalStyles} from '../styles/globalStyles';
const TimerScreen = () => {
const [colors] = useState(["#cbecdf", "#a97272", "#f2a4a4", "#483d8b", "#191970", "#cc66cc", "#cc99cc", "#99cccc", "#ccb399", "#cc9999",
"#99cc99", "#cc99cc", "#008080", "#800080", "#bada55", "#7193ff", "#ff4500", "#b00b69", "#ff0080", "#ff00ff", "#8000ff", "#0000ff", "#0080ff",
"#00ffff", "#00ff80", "#80ff00", "#ffff00", "#ff8000", "#ff0000", "#fd0404", "#ffccff", "#fff0f5", "#bbffff", "#381aaf", "#ff453c", "#cf9066",
"#b00b69", "#d3a625",])
const [players, setPlayers] = useState(
[{name: "kasper", timeLeft: "1"},
{name: "tatiana", timeLeft: "1"},
{name: "lars", timeLeft: "1"}]
);
const [intervalId, setIntervalId] = useState();
useEffect(() =>{
let newPlayers = [...players]
for(let player of newPlayers){
player.timeLeft = `${player.timeLeft}:00`
}
setPlayers(newPlayers);
}, [])
const startCountDown = (index) =>{
stopCountDowns();
countDown(index);
}
const stopCountDowns = () => clearInterval(intervalId)
const countDown = (index) => {
let newPlayers = [...players];
let mins = parseInt(newPlayers[index].timeLeft.split(':')[0])
let secs = parseInt(newPlayers[index].timeLeft.split(':')[1])
let interval = setInterval(() => {
console.log("i am running")
if(secs === 0 && mins !== 0 ){
mins--;
secs = 60;
}
if (secs !== 0){secs--}
newPlayers[index].timeLeft = `${mins}:${secs}`
console.log(newPlayers[index])
setPlayers(newPlayers)
}, 1000)
setIntervalId(interval)
}
return(
<ScrollView>
<View style={GlobalStyles.timerContainer}>
{players.map((player, index) =>
<TouchableOpacity style={{width: "50%", height: 150, backgroundColor: colors[index], alignItems: "center", justifyContent: "center"}} key={index} onPress={event => startCountDown(index)}>
<Text>{player.name}</Text>
<Text>{player.timeLeft}</Text>
</TouchableOpacity>
)}
</View>
</ScrollView>
)
}
export default TimerScreen;
import React,{useState,useffect}来自“React”;
从“react native”导入{ScrollView,View,Text,TouchableOpacity};
从“../styles/GlobalStyles”导入{GlobalStyles};
常量时间屏幕=()=>{
常量[颜色]=使用状态([“#cbecdf”、“#a97272”、“#f2a4a4”、“#483d8b”、“#191970”、“#cc66cc”、“#cc99cc”、“#ccb399”、“#ccb399”、“#cc9999”,
“#99cc99”、“#cc99cc”、“#008080”、“#800080”、“#bada55”、“#7193ff”、“#ff4500”、“#b00b69”、“#ff0080”、“#ff00ff”、“#ff00ff”、“#8000ff”、“#FF0000FF”、“#0080ff”,
“00ffff”、“00ff80”、“80ff00”、“ffff00”、“ff8000”、“ff0000”、“fd0404”、“ffccff”、“fff0f5”、“bbffff”、“381aaf”、“ff453c”、“cf9066”,
“#b00b69”、“#d3a625”、])
const[players,setPlayers]=useState(
[{名称:“卡斯珀”,时间倒数:“1”},
{名称:“塔蒂亚娜”,左上角:“1”},
{名称:“拉尔斯”,时间左图:“1”}]
);
const[intervalId,setIntervalId]=useState();
useffect(()=>{
让新玩家=[…玩家]
for(让玩家成为新玩家){
player.timeLeft=`${player.timeLeft}:00`
}
赛特球员(新球员);
}, [])
常量开始计数=(索引)=>{
停止倒计时();
倒计时(索引);
}
常量停止倒计时=()=>clearInterval(intervalId)
常数倒数=(索引)=>{
让新玩家=[…玩家];
let mins=parseInt(newPlayers[index].timeLeft.split(“:”)[0])
设secs=parseInt(newPlayers[index].timeLeft.split(“:”)[1])
let interval=setInterval(()=>{
log(“我正在运行”)
如果(秒===0&&min!==0){
分钟--;
秒=60;
}
如果(秒!==0){secs--}
新玩家[index].timeLeft=`${mins}:${secs}`
console.log(新玩家[索引])
赛特球员(新球员)
}, 1000)
setIntervalId(间隔)
}
返回(
{players.map((player,index)=>
开始计数(索引)}>
{player.name}
{player.timeLeft}
)}
)
}
导出默认时间屏幕;
以下是我认为您的代码存在的问题:
- 我想你想用一个平面列表。FlatList具有extradata属性,它是一个状态变量,当发生更改时,会触发列表的重新呈现
- 将intervalId保存为ref,以便其值在组件的所有生命周期中都保持不变
- 我创建了一个状态变量activePlayerIndex,并在其上绑定了一个启动activePlayer计时器的效果
- 为了使用FlatLists提供的extradata prop,我创建了一个状态变量totalActiveTime,该变量随所有计时器刻度递增
- 出于个人喜好,我将timeLeft设置为一个数字(后来转换为mm:ss),并添加了一个停止所有计时器的按钮
import React,{useState,useffect,useRef}来自'React';
从“react native”导入{FlatList、View、Text、TouchableOpacity、StyleSheet、Button};
//从“../styles/GlobalStyles”导入{GlobalStyles};
常量时间屏幕=()=>{
常量[颜色]=使用状态([“#cbecdf”、“#a97272”、“#f2a4a4”、“#483d8b”、“#191970”、“#cc66cc”、“#cc99cc”、“#ccb399”、“#ccb399”、“#cc9999”,
“#99cc99”、“#cc99cc”、“#008080”、“#800080”、“#bada55”、“#7193ff”、“#ff4500”、“#b00b69”、“#ff0080”、“#ff00ff”、“#ff00ff”、“#8000ff”、“#FF0000FF”、“#0080ff”,
“00ffff”、“00ff80”、“80ff00”、“ffff00”、“ff8000”、“ff0000”、“fd0404”、“ffccff”、“fff0f5”、“bbffff”、“381aaf”、“ff453c”、“cf9066”,
“#b00b69”、“#d3a625”、]);
常数时间长度=60;
//我发现以秒为单位处理时间并在渲染时将它们转换为mm:ss更容易
const[players,setPlayers]=useState([
{名称:“卡斯珀”,timeLeft:timerLength},
{名称:“tatiana”,timeLeft:timerLength},
{名称:“拉尔斯”,timeLeft:timerLength}
]);
//变量,表示哪个播放器处于活动状态
常量[activePlayerIndex,setActivePlayerIndex]=useState(-1)
//flatlist有一个参数,当变量更改时触发列表更新
const[totalActiveTime,setTotalTime]=useState(0);
//我认为您希望intervalId是一个ref,以便它的值在整个生命周期中都保持不变
const intervalRef=useRef();
//当activePlayer更改时要做的事情
useffect(()=>{
如果(activePlayerIndex<0)
返回
停止倒计时();
//在这里跑步
intervalRef.current=setInterval(()=>{
让activePlayer=players[activePlayerIndex];
如果(activePlayer.timeLeft>0){
activePlayer.timeLeft--;
log(activePlayer);
玩家[activePlayerIndex]=activePlayer;
赛特球员(球员);
//更新totalTime以触发平面列表重新渲染
setTotalTime(上一个=>上一个+1)
}
否则{
//有通知说玩家没时间了?
setActivePlayerIndex(-1);
}
}, 1000)
return()=>clearInterval(intervalRef.current)
},[activePlayerIndex])
常量停止倒计时=()=>clearInterval(intervalRef.current)
常量renderItem=({索引,项:{name,timeLeft}})=>{
返回(
setActivePlayerIndex(索引)}
>
{name}
{secondsToMinutes(timeLeft)}
)
}
//将秒转换为mm:ss形式
const secondsToMinutes=时间=>{
最小值=数学楼层(时间/60)
设秒=时间-(60*min)
返回`${min}:${seconds.toString().padStart(2,0)}`
}
返回(
索引}
extraData={totalActiveTime}
/>
{`游戏总时间:${secondsToMinutes(totalActiveTime)}`}