React-native: как визуализировать входные данные на основе числа, выбранного на предыдущем экране, и иметь возможность сохранять входные данные - PullRequest
0 голосов
/ 01 апреля 2019

У меня есть экран, на котором пользователь выбирает количество игроков для игры:

enter image description here

На следующем экране появляются некоторые текстовые вводы иЯ хочу иметь возможность именовать игроков, чтобы эти имена можно было хранить в базе данных:

enter image description here

Я использую FlatList для генерации этих полей,но кажется, что я не могу использовать onChangeText здесь.Если я пытаюсь ввести текст в любое из полей, я получаю эту ошибку:

enter image description here

Это код:

import React, {Component} from 'react';
import {View, Text, StyleSheet, ScrollView, Image, FlatList} from 'react-native';
import colors from '../config/colors';
import {TextField} from '../components/TextField';
import {PrimaryButton} from '../components/PrimaryButton';
import AsyncStorage from '@react-native-community/async-storage';

class player_names_screen extends Component {
    constructor (props) {
        super(props);
        this.state = {
            num_players: [],
            Player1: '',
            Player2: '',
            Player3: '',
            Player4: '',
            Player5: '',
            Player6: '',
            Player7: '',
            Player8: ''
        }
    }

    componentDidMount = () => {
        this.getNumPlayers();
    }
    
    //This is my nasty way of generating the correct amount of text fields based on the number selected
    getNumPlayers = async () => {
        let players = await AsyncStorage.getItem('Num_Players');
        this.setState({number_players: players});

        var players_json_middle = '';
        var x;
        for (x = 1; x <= players; x++) {
            player = '{"Player": "Player ';
            num_str = x.toString();
            if (x != players) {
                var player_num = player.concat(num_str, '"},');
            } else {
                var player_num = player.concat(num_str, '"}');
            }
            players_json_middle = players_json_middle.concat(player_num);
        }
        var players_json_start = '{"Players":[';
        var players_json_end = ']}';
        var players_json_str = players_json_start.concat(players_json_middle, players_json_end);
        var players_json = JSON.parse(players_json_str);
        this.setState({num_players: players_json.Players});
    }

    renderItem = ({item}) => {
        return (
            <TextField
                placeholder={item.Player}
                //This is my main problem. It isn't the way to change the state of the player names.
                onChangeText={() => this.setState(item.Player)}
            />
        )
    }
    
    signUp = async () => {
        let user = await AsyncStorage.getItem('email');

        const {Player1} = this.state;
        const {Player2} = this.state;
        const {Player3} = this.state;
        const {Player4} = this.state;
        const {Player5} = this.state;
        const {Player6} = this.state;
        const {Player7} = this.state;
        const {Player8} = this.state;
        
        fetch('fetch address is here [this isn't the problem]', {
            method: 'POST',
            headers: {
            'Accept': 'application/json',
            'Content-Type': 'application.json',
            },
            body: JSON.stringify({
                email: user,
                player1: Player1,
                player2: Player2,
                player3: Player3,
                player4: Player4,
                player5: Player5,
                player6: Player6,
                player7: Player7,
                player8: Player8
            })
        }).then((response) => response.json())
        .then((responseJson) => {
            this.props.navigation.navigate('round_start_screen');
        }).catch((error) => {
            console.error(error);
        });
    }

    render() {
        return (
            <ScrollView>
                <View style={{alignItems: 'center'}}>
                    <Text style={styles.headingText}>
                        Game Name
                    </Text>
                </View>
                <View style={styles.container}>
                    <Text style={styles.text}>
                        What are the players' names?
                    </Text>
                    <View style={{width: '80%'}}>
                    //Rendering the flatlist here
                        <FlatList
                            data={this.state.num_players}
                            renderItem={this.renderItem}
                            keyExtractor={(item, index) => index.toString()}
                        />
                    </View>
                    <PrimaryButton
                        onPress={() => this.signUp()}
                        label="Start Game"
                    >
                    </PrimaryButton>
                </View>
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        backgroundColor: colors.backgroundColor,
        margin: 10,
        paddingBottom: 5,
        borderWidth: 1,
        borderColor: colors.borderColor,
    },
    text: {
        fontSize: 24,
        color: colors.primaryText,
        marginTop: 10,
    },
    headingText: {
        fontSize: 24,
        fontWeight: '500',
        color: colors.primaryText,
        margin: 10,
    },
})

export default player_names_screen;

Есть ли способ назвать игроков здесь и сохранить их?Или весь этот подход бесполезен?Есть ли намного лучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 01 апреля 2019

Вы не предоставили ключ для обновления.Вам также необходимо использовать измененное текстовое значение.

renderItem = ({item, index}) => {
    return (
        <TextField
            placeholder={item.Player}
            onChangeText={(newText) => this.setState({[`Player${index}`]: newText})
        />
    )
}

Возможно, вы захотите использовать массив для этого состояния.Это позволит вам обновлять массив в позиции индекса, а не выполнять интерполяцию строк.

0 голосов
/ 01 апреля 2019

Если вам нужно быстрое решение, вы можете добавить случай переключения следующим образом:

renderItem = ({item, index}) => {
        return (
            <TextField
                placeholder={item.Player}
                onChangeText={() => this._updateState(item, index)}
            />
        )
    }

_updateState = (item, index) => {
 switch(index) {
  case 0: this.setState({Player1 :item.Player}); break;
  case 1: this.setState({Player2 :item.Player}); break;
  case 2: this.setState({Player3 :item.Player}); break;
  case 3: this.setState({Player4 :item.Player}); break;
  case 4: this.setState({Player5 :item.Player}); break;
  case 5: this.setState({Player6 :item.Player}); break;
  case 6: this.setState({Player7 :item.Player}); break;
  case 7: this.setState({Player8 :item.Player}); break
 }
}
...