typeerror: null не является объектом (оценивая towns.pu sh) - PullRequest
0 голосов
/ 26 февраля 2020

Я читаю эту книгу, издавая Мэннинга, «Реагируй на родной в действии», в учебнике в главе 6. Я пытаюсь создать приложение, которое можно использовать для добавления и отображения города, но, пытаясь добавить город, я получаю эта ошибка

typeerror: null не является объектом (оценивающим towns.pu sh)

, указывающим на

App. js строка 42, столбец 11

и

AddCity. js строка 30, столбец 35

. И я действительно не знаю, что делать, чтобы решить проблему.

На самом деле, я следую учебному пособию реагировать в действии Дабита Нейдера

Это

Приложение. js

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  AsyncStorage
} from 'react-native';

import Tabs from './src'

const key = 'state'

const initialState = [{
  city: 'Paris',
  country: 'France',
  id: 0,
  locations: []
},
{
  city: 'Tokyo',
  country: 'Japan',
  id: 1,
  locations: []
}]

export default class App extends Component {
  state = {
    cities: []
  }
  async componentDidMount() {
    try {
      let cities = await AsyncStorage.getItem(key)
      cities = JSON.parse(cities)
      this.setState({ cities })
    } catch (e) {
      console.log('error from AsyncStorage: ', e)
    }
  }
  addCity = (city) => {
    const cities = this.state.cities
    cities.push(city)
    this.setState({ cities })
    AsyncStorage.setItem(key, JSON.stringify(cities))
      .then(() => console.log('storage updated!'))
      .catch(e => console.log('e: ', e))
  }
  addLocation = (location, city) => {
    const index = this.state.cities.findIndex(item => {
      return item.id === city.id
    })
    const chosenCity = this.state.cities[index]
    chosenCity.locations.push(location)
    const cities = [
      ...this.state.cities.slice(0, index),
      chosenCity,
      ...this.state.cities.slice(index + 1)
    ]
    this.setState({
      cities
    }, () => {
      AsyncStorage.setItem(key, JSON.stringify(cities))
        .then(() => console.log('storage updated!'))
        .catch(e => console.log('e: ', e))
      })
  }
  render() {
    return (
      <Tabs
        screenProps={{
          cities: this.state.cities,
          addCity: this.addCity,
          addLocation: this.addLocation
        }}
      />
    )
  }
}

Это

AddCity. js

import React from 'react'
import {
  View,
  Text,
  StyleSheet,
  TextInput,
  TouchableOpacity
} from 'react-native'

import uuidV4 from 'uuid/v4'

import { colors } from '../theme'

class AddCity extends React.Component {
  state = {
    city: '',
    country: ''
  }
  onChangeText = (key, value) => {
    this.setState({ [key]: value })
  }
  submit = () => {
    if (this.state.city === '' || this.state.country === '') alert('please complete form')
    const city = {
      city: this.state.city,
      country: this.state.country,
      id: uuidV4(),
      locations: []
    }
    this.props.screenProps.addCity(city)
    this.setState({
      city: '',
      country: ''
    }, () => {
      this.props.navigation.navigate('Cities')
    })
  }
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.heading}>Cities</Text>
        <TextInput
          placeholder='City name'
          onChangeText={val => this.onChangeText('city', val)}
          style={styles.input}
          value={this.state.city}
        />
        <TextInput
          placeholder='Country name'
          onChangeText={val => this.onChangeText('country', val)}
          style={styles.input}
          value={this.state.country}
        />
        <TouchableOpacity onPress={this.submit}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>Add City</Text>
          </View>
        </TouchableOpacity>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  button: {
    height: 50,
    backgroundColor: '#666',
    justifyContent: 'center',
    alignItems: 'center',
    margin: 10
  },
  buttonText: {
    color: 'white',
    fontSize: 18
  },
  heading: {
    color: 'white',
    fontSize: 40,
    marginBottom: 10,
    alignSelf: 'center'
  },
  container: {
    backgroundColor: colors.primary,
    flex: 1,
    justifyContent: 'center'
  },
  input: {
    margin: 10,
    backgroundColor: 'white',
    paddingHorizontal: 8,
    height: 50
  }
})

export default AddCity

реагировать -навигатор используется версия 2.0.1

1 Ответ

0 голосов
/ 26 февраля 2020

Массивы не являются примитивными типами данных, поэтому они являются ссылками по адресу.

В вашем коде -

 addCity = (city) => {
    const cities = this.state.cities
    cities.push(city)
    this.setState({ cities })
    AsyncStorage.setItem(key, JSON.stringify(cities))
      .then(() => console.log('storage updated!'))
      .catch(e => console.log('e: ', e))
  }

Вы в основном изменяете массив городов напрямую, Ваш push будет напрямую изменять состояние, вместо этого сделайте это -

 addCity = (city) => {
    this.setState({ cities: [...this.state.cities, city]})
    AsyncStorage.setItem(key, JSON.stringify(cities))
      .then(() => console.log('storage updated!'))
      .catch(e => console.log('e: ', e))
  }

То же самое для других мест. Надеюсь, это поможет вам.

...