Как передать вход в хранилище Redux и отобразить отфильтрованные данные соответственно - PullRequest
0 голосов
/ 16 января 2020

У меня проблемы с передачей объекта из родительского в дочерний компонент. Я читал различные подобные посты, но ни одно из решений не сработало.

Сообщение об ошибке: Ошибка типа: Невозможно прочитать свойство 'map' из неопределенного

Родитель: (Приложение. js)

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchData } from '../actions/actions';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      filter: "",
      data: [],
      filteredData: []
    };
  }

  componentDidMount() {
    this.props.dispatch(fetchData());
  };

  render() {

    const { filter, data } = this.state;
    const lowercasedFilter = filter.toLowerCase();
    const filteredData = data.filter(item => {
      return Object.keys(item).some(key =>
        item[key].toString().toLowerCase().includes(lowercasedFilter)
      );
    });

    return (
      <div>
        <UserList filteredData={filteredData}/>
        {console.log(this.props.myData.Brastlewark)}
      </div>
    );
  }
}

const mapStateToProps = ({ things: { myData, isFetching } }) => ({
  myData,
  isFetching
});


export default connect(mapStateToProps)(App);

Ребенок: (Список пользователей. js)

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchData } from '../actions/actions';
import 'bootstrap/dist/css/bootstrap.min.css';
import '../layout.css'

class UserList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      filter: "",
      data: [],
      filteredData: {}
    };
  }

  componentDidMount() {
    this.props.dispatch(fetchData());
  };

  handleChange = event => {
    this.setState({ filter: event.target.value });
    this.setState((state, props) => ({
      data: this.props.myData.Brastlewark
    }))
  };

  render() {
    const {filteredData} = this.props;
    return (
      <div className="container-fluid">
        <div className="jumbotron">
          <h2>
            <input value={this.props.filter} onChange={this.handleChange} placeholder="please search" />
          </h2>
            {!this.props.isFetching && <div> You may start searching for Orcs in the vilage by typing into the search box above. </div>}
        </div>

        <div className="container">
          <div className="row">
              {filteredData.map(item => (
              <div className="col-md-4 col-xs-6" key={item.id}>
                <div className="card">
                    <img className="card-img-top img-fluid" src={item.thumbnail} alt={item.age}/>
                  <div className="card-block">
                    <h5 className="card-title">{item.professions.toString().split(', ')}</h5>
                    <p className="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
                    <p className="card-text"><small className="text-muted">Last updated 1 sec ago</small></p>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      {console.log(this.props.myData.Brastlewark)}
      </div>
    );
  }
}

const mapStateToProps = ({ things: { myData, isFetching } }) => ({
  myData,
  isFetching
});


export default connect(mapStateToProps)(UserList);

Действие. js

export const REQUEST_DATA = 'REQUEST_DATA'; // action to represent waiting for response
export const GET_DATA_FIRST = 'GET_DATA_FIRST'; // action to represent receiving of data

export const requestData = () => ({ type: REQUEST_DATA });

export const getDataFirst = myData => ({ type: GET_DATA_FIRST, myData });

export const fetchData = () => dispatch => {
    dispatch(requestData());
    return getData().then(things => {
    // simulated delay
    setTimeout(() => {
        return dispatch(getDataFirst(things))
    }, 1000);
});
};

const getData = async () => {
    const res = await fetch('https://raw.githubusercontent.com/rrafols/mobile_test/master/data.json');
    return await res.json();
}

Редуктор (редуктор. js)

import { combineReducers } from 'redux';
import { GET_DATA_FIRST, REQUEST_DATA } from '../actions/actions';

const initialState = {
  isFetching: false,
  myData: []
};

const things = (state = initialState, action) => {
  switch (action.type) {
    case REQUEST_DATA:
        return {
        ...state,
        isFetching: true
        };
    case GET_DATA_FIRST:
        return {
        ...state,
        isFetching: false,
        myData: action.myData
        };
    default:
        return state;
  }
};

const rootReducer = combineReducers({
  things // this key can be called anything, 'things' is just an example
});

export default rootReducer;

Возможно, кто-нибудь мог бы помочь мне преобразовать эту часть в редукцию или просто самым простым способом, получив filtedData, определяемый входным текстом?

Заранее спасибо

1 Ответ

1 голос
/ 16 января 2020

Возможно, проблема в том, что функция .map работает до того, как передается data. Эта ошибка обычно появляется, когда вы пытаетесь go через неопределенный объект.

Попробуйте этот код:

<div className="row">
    {filteredData && filteredData.map(item => (
        // do stuff with your item
    ))}
</div>

Упоминание имени переменной перед тем, как что-то делать с ней, проверяет, является ли это undefined/null или нет. Если это не так, go включится и сделает то, что вы запрограммировали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...