我正在React-Native上创建一个记忆卡游戏,我正在使用此存储库来制作Flip Animation https://github.com/lhandel/react-native-card-flip。
在第1级上,当我匹配所有卡时,我将状态设置为更改级别,而在第2级卡上仍处于翻转状态,则我希望它处于初始状态。
解决问题之前的1级: Level 1 Image
解决等级1后的等级2: Level 2 Image
我想要的是在2级上,它应该像最初一样(如在1级中)呈现背面的导入的CardFlip组件绘图卡。
我使用的是本机反应,而不是博览会。将我的代码放入App.js文件中,并导入card-flip存储库,然后使用react-native运行Android代码。
import React, { Component } from 'react';
import {
StyleSheet,
Image,
View, Dimensions, Text,
TouchableOpacity
} from 'react-native';
import CardFlip from 'react-native-card-flip';
export default class App extends Component<Props> {
constructor(props){
super(props)
this.state = {
page: true,
level: 1,
tries: 0,
}
this.width = Dimensions.get('window').width;
this.levels = {
1:{cards:4,rowItems:2,tries:3,card_width:(this.width/2)-15},
2:{cards:6,rowItems:2,tries:5,card_width:(this.width/2)-15},
3:{cards:8,rowItems:2,tries:6,card_width:(this.width/2)-70},
4:{cards:12,rowItems:3,tries:8,card_width:(this.width/3)-50},
5:{cards:14,rowItems:3,tries:9,card_width:(this.width/3)-50},
6:{cards:18,rowItems:3,tries:12,card_width:(this.width/3)-50},
7:{cards:24,rowItems:4,tries:16,card_width:(this.width/4)-15},
8:{cards:30,rowItems:5,tries:20,card_width:(this.width/5)-15},
9:{cards:34,rowItems:5,tries:22,card_width:(this.width/5)-15},
10:{cards:40,rowItems:5,tries:25,card_width:(this.width/5)-15}
};
this.dimens = {width: this.levels[this.state.level].card_width, height: this.levels[this.state.level].card_width};
}
go_next = () =>{
this.setState({page: false, tries:0, level: 1});
};
go_home = () =>{
this.setState({page: true});
};
tried = ()=>{
this.setState({tries: this.state.tries+1});
};
level_up = ()=>{
console.log("level up: ", this.state.level+1);
this.setState({level: this.state.level+1, tries: 0});
};
level_restart = ()=>{
console.log("level restarted: ", this.state.level);
this.setState({level: this.state.level, tries: 0});
}
render() {
if (this.state.page) {
return (
<View style={styles.container}>
<Text style={styles.heading}>Cardy</Text>
<Text>Color Memory Game for Kids</Text>
<TouchableOpacity onPress={this.go_next}>
<Image style={{marginBottom:30}} source={require("./assets/play.png")}></Image>
</TouchableOpacity>
</View>
);
} else {
return (
<View style={{flex:1}}>
<View style={{flex:.1,alignItems: 'center',justifyContent:'flex-end',marginTop:20}}><Text style={styles.subheading}>Level {this.state.level}</Text><Text>Tries Remaining: {(this.levels[this.state.level].tries-this.state.tries)}</Text></View>
<Cards dimens={this.dimens} cards={this.levels[this.state.level].cards} rowItems={this.levels[this.state.level].rowItems} tried={this.tried.bind(this)} level_up={this.level_up.bind(this)} level_restart={this.level_restart.bind(this)} level={this.state.level} tries={this.state.tries} total_tries={this.levels[this.state.level].tries} />
<View style={{alignItems: 'center',flex:.1}}>
<TouchableOpacity onPress={this.go_home}>
<Text>← Go Home</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
}
class Cards extends Component<props> {
constructor(props){
super(props)
this.color='';
this.ckey='';
this.tries=0;
this.matched=0;
this.level = this.props.level;
}
shouldComponentUpdate(nextProps, nextState){
if( this.level != nextProps.level || nextProps.tries==0 )
return true;
else return false;
}
do_flip = (color, ckey)=>{
if( this.color != '' ){ // second card flip
this.props.tried();
this.tries++;
if( this.color == color ){ //card matched
this.matched++;
this["card"+ckey].flip();
if( this.matched == this.props.cards/2 ){
this.tries=0;
this.matched=0;
alert("Level completed successfully.");
this.props.level_up();
}
else if( this.tries == this.props.total_tries ){
alert("Sorry, Level failed, try again.");
this.tries=0;
this.matched=0;
this.props.level_restart();
}
} else { // card not matched
var pkey = this.ckey;
this["card"+pkey].flip();
if( this.tries == this.props.total_tries ){
this.tries=0;
this.matched=0;
alert("Sorry, Level failed, try again.");
this.props.level_restart();
}
}
this.color='';
this.ckey='';
} else { // first card flip
this["card"+ckey].flip();
this.color=color;
this.ckey=ckey;
}
};
shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
generate_cards = ()=>{
const inner_cards = this.props.rowItems;
const main_loops = Math.ceil(this.props.cards/inner_cards);
const colors = ["blue","green","red","yellow","black","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","blanchedalmond","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","yellowgreen"];
var selected_colors = colors.slice(0, this.props.cards/2);
selected_colors = selected_colors.concat(selected_colors);
this.shuffleArray(selected_colors);
var cd = 0;
let row = [];
let card = [];
var list = selected_colors.map( (color, key)=> {
if( cd == 0 ) { card = []; }
card.push(
<CardFlip style={this.props.dimens} key={key} ref={(card) => this["card"+key] = card}>
<TouchableOpacity activeOpacity={1} style={this.props.dimens} onPress={() => {this.do_flip(color,key); }} >
<Image style={this.props.dimens} source={require("./assets/robot.png")}></Image>
</TouchableOpacity>
<TouchableOpacity activeOpacity={0} style={[this.props.dimens]}>
<View style={[{backgroundColor:color}, this.props.dimens]}></View>
</TouchableOpacity>
</CardFlip>
);
cd++;
if( cd==inner_cards || key == selected_colors.length-1 ){
cd=0;
return <View key={key+"a"} style={{flex:1,flexDirection:'row',justifyContent:'space-evenly',alignItems: 'center'}}>{card}</View>
}
});
return list;
}
render(){
return (
<View style={{flex:.8}}>
{this.generate_cards()}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
heading:{
fontSize: 40,
color: 'green',
fontWeight:'bold',
marginBottom: 20
},
subheading:{
fontSize: 30,
color: 'green',
fontWeight:'bold',
marginBottom: 20
},
boxContainer: {
flex: 1,
alignItems: 'center',
flexDirection: 'column',
backgroundColor:'yellow'
}
});
答案 0 :(得分:0)
您正在初始化构造函数中的状态,该状态在组件安装时仅运行一次。因此,当父组件的状态发生变化时,它会将道具传递给子组件,但是在这种情况下子组件的构造函数未运行,因此子组件的状态不符合您的预期。
类似的事情会起作用。在子组件中定义componentWillReceiveprops
,如果新收到的道具与前一个道具不同,则设置setState。
我正在使用一个库lodash来比较对象,数组等。我向您推荐
示例
import React, {Component} from 'react'
import _ from 'lodash';
class ChildComponent extends Component{
componentWillReceiveProps(nextProps){
if(!_.isEqual(this.props.something, nextProps.something) && Boolean(nextProps)){
this.setState({something: nextProps.something})
}
}
render(){
return(
)
}
}
注意:尽量不要无条件地setState
进入componentWillReceiveProps
或componentDidUpdate
,以确保不会导致您进入设置状态的无限循环