Реагировать Фильтровать состояние, не изменяя массив - PullRequest
0 голосов
/ 13 января 2020

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

Это, кажется, популярный вопрос, и я проверил здесь , здесь и здесь .

import React, { Component } from 'react';
import axios from 'axios';
import Sidebar from './components/Sidebar'
import Map from './components/Map'

require('dotenv').config();

class App extends Component {
  state = {
    incidents: [],
    map: false,
    options: []
  }

  async componentDidMount() {
    const res = await axios.get('https://data.sfgov.org/resource/wr8u-xric.json', {
      params: {
        "$limit": 500,
        "$$app_token": process.env.APP_TOKEN
      }
    })

    const incidents = res.data;
    this.setState({ incidents });

    console.log(incidents)

    this.getOptions()
  };

  getMap = () => {
    this.setState({ map: true });
    console.log(this.state.options)
  }

  handleChange = (e) => {
    const items =  this.state.incidents.filter(incident => incident['zip_code'] === e.target.value)
    this.setState({incidents: items})
  }

  getOptions = () => {
    this.state.incidents.map(incident => {
      if(!this.state.options.includes(incident['zip_code'])){
        this.state.options.push(incident['zip_code'])
      }
    })
  }

  render() {
    return (
      <div>
        <h1> San Francisco Fire Incidents</h1>
        <button onClick={this.getMap}> Get Map</button>

        <div id="main">
          <div style={{ width: '20%', height: '900px', display: 'inline-block', overflow: 'scroll', marginRight: '2px' }}>
            <span> Zip Code</span>
            <form>
              <select value={this.state.value} onChange={this.handleChange}>
              {this.state.options.map(option => (
                <option value={option} key={option}>{option}</option>
              ))}

              </select>
            </form>
          </div>
          {
            this.state.map ? <Map incidents={this.state.incidents} /> : ''
          }
        </div>
      </div>
    );
  }
}

export default App;

Ответы [ 3 ]

2 голосов
/ 13 января 2020

Проблема в том, что вы нигде не поддерживаете начальное состояние.

Так что после изменения состояния и удаления элементов ожидается, что переменная состояния не будет содержать все исходные элементы.

Изменитесь на что-то вроде следующего:

import React, { Component } from 'react';
import axios from 'axios';
import Sidebar from './components/Sidebar'
import Map from './components/Map'

require('dotenv').config();

class App extends Component {
  state = {
    initialIncidents: [], 
    incidents: [],
    map: false,
    options: []
  }

  async componentDidMount() {
    const res = await axios.get('https://data.sfgov.org/resource/wr8u-xric.json', {
      params: {
        "$limit": 500,
        "$$app_token": process.env.APP_TOKEN
      }
    })

    const incidents = res.data;
    this.setState({ initialIncidents: incidents });

    console.log(incidents)

    this.getOptions()
  };

  getMap = () => {
    this.setState({ map: true });
    console.log(this.state.options)
  }

  handleChange = (e) => {
    const items =  this.state.initialIncidents.filter(incident => incident['zip_code'] === e.target.value)
    this.setState({incidents: items})
  }

  getOptions = () => {
    this.state.incidents.map(incident => {
      if(!this.state.options.includes(incident['zip_code'])){
        this.state.options.push(incident['zip_code'])
      }
    })
  }

  render() {
    return (
      <div>
        <h1> San Francisco Fire Incidents</h1>
        <button onClick={this.getMap}> Get Map</button>

        <div id="main">
          <div style={{ width: '20%', height: '900px', display: 'inline-block', overflow: 'scroll', marginRight: '2px' }}>
            <span> Zip Code</span>
            <form>
              <select value={this.state.value} onChange={this.handleChange}>
              {this.state.options.map(option => (
                <option value={option} key={option}>{option}</option>
              ))}

              </select>
            </form>
          </div>
          {
            this.state.map ? <Map incidents={this.state.incidents} /> : ''
          }
        </div>
      </div>
    );
  }
}

export default App;
0 голосов
/ 13 января 2020

this.state.incidents содержит все инциденты, и когда пользователь делает первый выбор, вы меняете массив incidents. Второй выбор фильтрует уже отфильтрованные инциденты из первого выбора и возвращает пустой. Это может быть причиной этой проблемы.

  const items =  this.state.originalIncidents.filter(incident => incident['zip_code'] === e.target.value)
    this.setState({incidents: items})
0 голосов
/ 13 января 2020

Я думаю, что в этой части что-то не так

getOptions = () => {
this.state.incidents.map(incident => {
  if(!this.state.options.includes(incident['zip_code'])){
    this.state.options.push(incident['zip_code'])
  }
})

}

Вы всегда изменяете параметры состояния при поиске. Если результатов не найдено, массив параметров будет пустым.

Попробуйте сделать что-то подобное.

  getOptions = () => {
    let options = [...this.state.options]
    this.state.incidents.map(incident => {
      if(!this.state.options.includes(incident['zip_code'])){
        options.push(incident['zip_code'])
      }
    })
    this.setState({options});
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...