简体   繁体   中英

How to update component in react native with a store redux

I'm making an app in react-native and I use a store redux to manage the player, each player has an id and a name. So I have already made action to add and set the player, and all work fine, when I had a player, the component is updated and the same for the setPlayer. Now I want to make an action for the delete, but when I pressed the button to delete the component is nos updated, but I'm sure that the player is delete in the background.

Here the code ( component for the player )


import React from 'react'
import Ionicons from 'react-native-vector-icons/Ionicons'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons' // Pour ajouter la corbeille
import { vw, vh } from 'react-native-viewport-units-fix' 
import { View, TouchableOpacity, StyleSheet, TextInput, ScrollView } from 'react-native'
import { connect } from 'react-redux'

const heightPlayer = 8*vh;
const sizeIcon     = 12*vw;


class JoueurListe extends React.Component {

    _listItems() {
        return (
            
            this.props.tabJoueur.map((joueur) =>
                <View 
                    style={styles.container_player}
                    key={joueur.id}>          
                    <TextInput
                        style={[this.props.style, styles.player]}
                        maxLength={12}
                        placeholder={joueur.player_name}
                        placeholderTextColor='#446C85'
                        onChangeText={(text) => this._setPlayer(text, joueur.id)}
                        />
                    <TouchableOpacity onPress={() => this._delPlayer(joueur.id)}>
                        <MaterialCommunityIcons
                            name={"delete"}
                            size ={sizeIcon}
                            style={styles.delete}
                        />
                    </TouchableOpacity>
                </View> )
        )
    }

    _delPlayer(index) {
        const action = { type:'DEL_PLAYER', index: index}
        this.props.dispatch(action)

    }

    _setPlayer(text, index) {
        let action;
        if ( text === "") action = { type: "SET_PLAYER", player_name: "Joueur "+ index, index: index }
        else              action = { type: "SET_PLAYER", player_name: text, index: index }

        this.props.dispatch(action)
    }

    _showPlayer() {
        return (
            <View style={{flexDirection: 'column', width: '100%'}}>
                {this._listItems()}
            </View>
        )
    }

    _addPlayer() {
        const action = { type: "ADD_PLAYER", player_name: "Joueur " }
        this.props.dispatch(action)
    }

    render() {
        return (
            <ScrollView style={styles.main_container}>
                {this._showPlayer()}
                <TouchableOpacity style={styles.container_player} onPress={() => this._addPlayer()}>
                    <Ionicons name="add-circle" size={sizeIcon}/>
                </TouchableOpacity>
            </ScrollView>
        )
    }
}

const styles = StyleSheet.create({
    main_container: {
        flexDirection: 'column',
        width: '100%',
        top: '15%',
        marginLeft: 25*vw,
        marginBottom: 20*vh
    },
    container_player: {
        flexDirection: 'row',
        justifyContent: 'center',
        height: heightPlayer,
        borderRadius: 15,
        borderColor: '#BFB9B9',
        borderWidth: 2,
        textAlign: 'center',
        backgroundColor: 'white',
        marginBottom: '4%',
        width: '75%',
        paddingLeft: 2*vw,
        paddingRight: 2*vw
    },
    player: {
        left: '0%',
        color: '#446C85',
        fontSize: 20,
        width: '75%'
    },
    title: {
        fontSize: 32,
    },
    delete: {
        right: '0%'
    }
    
})

const mapStateToProps = (state) => {
    return state
  }
  
export default connect(mapStateToProps)(JoueurListe)

And the stor


let idJoueur = 1;

const initialState = {
    tabJoueur: [{id: 1, player_name: "Joueur 1"}]
}

function reducerPlayer(state = initialState, action) {
    let nextState = state

    switch (action.type) {
        case 'ADD_PLAYER':
            return nextState = {
                tabJoueur: [...state.tabJoueur, { id: ++idJoueur , player_name: action.player_name + idJoueur } ]                
            }
        case 'SET_PLAYER':
            nextState.tabJoueur[action.index-1] = {id: action.index, player_name: action.player_name }
            return nextState
        case 'DEL_PLAYER':
            if (idJoueur > 1) {
                nextState.tabJoueur.splice(action.index-1, 1)
                for (let i=action.index-1;i<nextState.tabJoueur.length;i++){
                    let tmp = nextState.tabJoueur[i].player_name
                    if ( tmp.includes("Joueur ") )tmp="Joueur " + (i+1)
                    nextState.tabJoueur[i] = { id: i+1, player_name: tmp}
                }

                console.log(nextState.tabJoueur)

                idJoueur--
            }
            return nextState
        default:
            return nextState
    }
    
}

export default reducerPlayer

Your component is already right, your reducer is not.

You are still modifying the original object there - just because you do let nextState = state does not mean that nextState is a new state. It actually is just a pointer to the original state, so you are still modifying that.

As all this immutable logic can get quite complicated I would recommend you to check out the official Redux Toolkit which allows you to actually write "mutating" code in their reducers that ends up in an immutable copy automatically:modern redux with redux toolkit (from the official redux tutorials)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM