[英]Child component inside modal unexpectedly resets to default state, React Native
我有一个父组件 - LeagueSelect - 和一个子组件TeamSelect。
LeagueSelect是一个React Native模式。
当我打开LeagueSelect时,在LeagueSelect模式中进行调整,折叠模态,然后再次打开它,状态更改将被保留。
如果我打开LeagueSelect,在LeagueSelect模式中调整TeamSelect,折叠模态,再次打开它,状态更改不会保留。
为了提供上下文,当模态(LeagueSelect)打开时,这就是它的样子; 第一个红色框是LeagueSelect的一部分,第二个红色框是TeamSelect的一部分:
这是我的LeagueSelect组件; 我认为问题发生在setModalVisible中,因为当我在consoleWillUnmount上调度状态时,控制台日志会读取正确的状态:
class LeagueSelect extends Component {
constructor(props) {
super(props)
this.state = {
modalVisible: false,
checked: [],
checkedLeagues: [],
uncheckedLeagues: [],
checkMessage: '',
firstString: []
}
}
setModalVisible(visible) {
this.setState({modalVisible: visible})
if(this.state.checked.length === 0) {
this.props.league.map(
(v, i) => {
this.state.checked.push(true)
this.state.checkedLeagues.push(v.acronym)
}
)
}
this.setState({ checkMessage: '' })
matchedTeams = []
if(undefined !== this.props.teamObject) {
this.props.teamObject.map(
(v, i) => {
if(this.state.checkedLeagues.includes(v.league.acronym)){
matchedTeams.push(v.team_name)
}
}
)
}
queryString = []
//encodes the teams that have their leagues selected
matchedTeams.map(
(v, i) => {
if (queryString.length < 1) {
queryString.push(`?team=${v}`)
} else if (queryString.length >= 1 ) {
queryString.push(`&team=${v}`)
}
}
)
queryString = queryString !== undefined ? queryString.join('') : ''
axios.get(`http://localhost:4000/reports${queryString}`)
.then(response => {
this.props.loadCards(response.data)
})
}
componentDidMount() {
this.props.loadLeagues()
this.props.loadTeams()
}
componentDidUpdate(){
console.log(this.props.checkedLeagues)
console.log('in league - in update - checked Teams', this.props.checkedTeams)
this.props.changeLeagues(this.props.league, this.state.checkedLeagues, this.props.checkedTeams, this.props.queryTeams, this.props.teamObject)
}
render(){
return (
<View style={{ position: 'relative'}}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}
>
<View
style={{
marginTop: 100
}}
>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}
>
<Image
source={require('../assets/exit.png')}
style={{
height: 20,
width: 20,
left: 320,
resizeMode: 'contain'
}}
/>
</TouchableHighlight>
<Text
style={{
paddingTop: 8,
paddingLeft: 5,
fontSize: 15,
fontFamily: 'Helvetica',
fontSize: 13
}}
>LEAGUE SELECT</Text>
<View
style={{
flexDirection:"row",
paddingLeft: 10
}}
>
{this.props.league === null ?'' : this.props.league.map(
(v, i) => {
return(
<View
key={i}
style={{
alignSelf: 'flex-end',
flexDirection:"row",
top: 4,
paddingRight: 10
}}
>
<Check
checked={this.state.checked[i]}
index={i}
value={v.acronym}
changeCheck={this.changeCheck}
style={{
paddingRight: 10
}}
/>
</View>
)
}
)}
</View>
<Text
style={{
paddingLeft: 10,
paddingTop: 12,
fontStyle: 'italic',
color: '#F4AF0D'
}}
>{this.state.checkMessage}</Text>
<TeamSelect />
</View>
</Modal>
<TouchableHighlight
onPress={() => {
this.setModalVisible(true);
}}>
<Icon
style={{
position: 'absolute',
top: -34,
right: 10,
fontSize: 25,
color: 'grey'
}}
name='settings'
/>
</TouchableHighlight>
</View>
);
}
}
function mapStateToProps(state) {
return {
league: state.league.league,
team: state.team.team,
checkedLeagues: state.league.checkedLeagues,
checkedTeams: state.league.checkedTeams,
queryTeams: state.league.queryTeams,
teamObject: state.league.teamObject
}
}
export default connect(mapStateToProps, { loadCards, loadLeagues, loadTeams, changeLeagues })(LeagueSelect)
这是TeamSelect组件,其中第二个红色框的选择是:
class TeamSelect extends Component {
constructor(props) {
super(props)
this.state = {
checked: [],
checkedTeams: [],
teamObject: [],
queryString: [],
accordionStatus: [true, true, true]
}
}
componentDidMount(){
console.log('did mount - checked Teams State', this.state.checkedTeams)
//updates checked teams on load
if(this.state.count === false && this.state.checkedTeams.length === 0 && this.state.checked.length === 0){
this.setState({ count: true})
this.props.team.map(
(v, i) => {
if(this.props.checkedLeagues.includes(v.league.acronym)) {
this.state.checked.push(true)
this.state.checkedTeams.push(v.team_name)
this.state.teamObject.push(v)
} else if (this.state.checkedTeams !== undefined) {
this.state.checked.push(false)
}
}
)
this.forceUpdate()
}
}
componentWillUnmount(){console.log("unmount - count", this.state.count)
console.log('will unmount - checked Teams State', this.state.checkedTeams)
}
componentDidUpdate(){
this.props.changeLeagues(this.props.league, this.props.checkedLeagues, this.state.checkedTeams, this.state.queryString, this.state.teamObject)
}
changeCheck = (index, name, teamObject) => {
//updates checked team state
//prevents all teams being unselected
if(name === this.state.checkedTeams[0]) {
this.setState({ checkMessage: `Don't you want something to look at?` })
} else {
if(!this.state.checkedTeams.includes(name)){
this.state.checkedTeams[this.state.checkedTeams.length] = name
this.setState({ checkedTeams: [...this.state.checkedTeams] })
//sets team object with new team object
this.state.teamObject[this.state.teamObject.length] = teamObject
this.setState({ teamObject: this.state.teamObject })
} else {
newChecked = this.state.checkedTeams.filter(v => { return v !== name})
this.setState({ checkedTeams: newChecked })
//removes team object and sets new state
newObjectChecked = this.state.teamObject.filter(v => { return v.team_name !== teamObject.team_name})
this.setState({ teamObject: newObjectChecked })
}
//updates checkbox for specific space
this.state.checked[index] = !this.state.checked[index]
this.setState({ checked: this.state.checked })
}
}
changeTeamSelect = (index) => {
this.state.accordionStatus[index] = !this.state.accordionStatus[index]
this.setState({ accordionStatus: this.state.accordionStatus})
}
render(){
return(
<View>
<View>
<Text
style={{
fontFamily: 'Helvetica',
fontSize: 13,
paddingLeft: 5,
paddingBottom: 5
}}
onPress={()=> this.changeTeamSelect(0)}
>
NFL TEAM SELECT
</Text>
</View>
{
this.state.accordionStatus[0] === false ? null :
<View
style={{
flexDirection: 'row',
paddingLeft: 10,
flexWrap: 'wrap'
}}
>
{
this.props.team.map(
(v, i) => {
if(v.league.acronym === 'NFL'){
return(
<Check
key={i}
checked={ /*this.props.checkedLeagues.includes(v.league.acronym) ?*/ this.state.checked[i] /*: false*/ }
index={i}
teamObject={v}
value={v.team_name}
changeCheck={this.changeCheck}
/>
)
}
}
)
}
</View>
}
<View>
<Text
style={{
fontFamily: 'Helvetica',
fontSize: 13,
paddingLeft: 5,
paddingBottom: 5
}}
onPress={()=> this.changeTeamSelect(1)}
>
NBA TEAM SELECT
</Text>
</View>
{
this.state.accordionStatus[1] === false ? null :
<View
style={{
flexDirection: 'row',
paddingLeft: 10,
flexWrap: 'wrap'
}}
>
{
this.props.team.map(
(v, i) => {
if(v.league.acronym === 'NBA'){
return(
<Check
key={i}
checked={ /*this.props.checkedLeagues.includes(v.league.acronym) ?*/ this.state.checked[i] /*: false*/ }
index={i}
teamObject={v}
value={v.team_name}
changeCheck={this.changeCheck}
/>
)
}
}
)
}
</View>
}
<View>
<Text
style={{
fontFamily: 'Helvetica',
fontSize: 13,
paddingLeft: 5,
paddingBottom: 5
}}
onPress={()=> this.changeTeamSelect(2)}
>
MLB TEAM SELECT
</Text>
</View>
{
this.state.accordionStatus[2] === false ? null :
<View
style={{
flexDirection: 'row',
paddingLeft: 10,
flexWrap: 'wrap'
}}
>
{
this.props.team.map(
(v, i) => {
if(v.league.acronym === 'MLB'){
return(
<Check
key={i}
checked={ /*this.props.checkedLeagues.includes(v.league.acronym) ?*/ this.state.checked[i] /*: false */}
index={i}
teamObject={v}
value={v.team_name}
changeCheck={this.changeCheck}
/>
)
}
}
)
}
</View>
}
</View>
)
}
}
function mapStateToProps(state) {
return {
league: state.league.league,
team: state.team.team,
checkedLeagues: state.league.checkedLeagues,
checkedTeams: state.league.checkedTeams,
queryTeams: state.league.queryTeams
}
}
export default connect(mapStateToProps, { loadCards, changeLeagues })(TeamSelect)
需要注意的是,我使用redux来更新状态,将其放入商店,然后在组件再次安装时使用它。 有趣的是,this.state.checkedLeagues在第一个组件中保留了应该存在的状态,但是,this.state.checkedTeams不会在第二个组件中保留它的状态。 有什么想法吗?
编辑:
这是我的LeagueReducer:
let defaultState = {
league: null,
checkedLeagues: null,
checkedTeams: null,
queryTeams: null,
teamObject: null
}
export function LeagueReducer(state = defaultState, action){
if(action.type === "CHANGE_LEAGUES") {
return {
...state,
league: action.league,
checkedLeagues: action.checkedLeagues,
checkedTeams: action.checkedTeams,
queryTeams: action.queryTeams,
teamObject: action.teamObject
}
} else {
return state
}
}
看起来你可能没有正确更新redux商店。 记住不要使用像push
一样改变数组的数组函数。 您需要使用concat
函数来返回一个新数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.