Реактивный компонент не отражает текущее состояние магазина - PullRequest
0 голосов
/ 19 мая 2019

Я реализовал компонент, который показывает курсы.Внутри того же компонента есть функция фильтрации курсов, когда пользователь ищет определенный курс.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я отправляю действие для фильтрации курсов, в хранилище редуксов указывается, что состояние курсов было обновлено и содержит только курсы, соответствующие поисковому запросу, но компонент не отражает новое состояние (т.е. пока показывает все курсы).Как я могу решить эту проблему?

Вот что я реализовал до сих пор

Действие

export const retrieveAllCourses = (url, query) => dispatch => {
  return axios
    .get(url + `?title=${query}`, {
      headers: myHeaders
    })

    .then(res => {
      const fetchall = {
        type: ACTION_TYPE.VIEW_COURSES,
        payload: res.data.courses
      };
      dispatch(fetchall);
    })
    .catch(error => {
      toast.error(error, { autoClose: 3500, hideProgressBar: true });
    });
};

Редуктор

import ACTION_TYPE from "../../actions/actionTypes";

const initialState = {
  courses: [],
};

const coursesReducer = (state = initialState, action) => {
  switch (action.type) {

  case ACTION_TYPE.VIEW_COURSES:
    return {
      ...state,
      courses: state.courses.concat(action.payload.results),
    };

  default:
    return state;
  }
};

export default coursesReducer;

Поиск компонента

import React from "react";
import PropTypes from "prop-types";

class Search extends React.Component {
  state = {
    search: ""
  };

  handleChange = ev => {
    ev.preventDefault();
    const { onChange } = this.props;
    const search = ev.target.value;
    this.setState({ search });
    if (onChange) {
      onChange(search);
    }
  };

  handleSearch = ev => {
    ev.preventDefault();
    const { onSearch } = this.props;
    const { search } = this.state;
    if (onSearch) {
      onSearch(search);
    }
  };

  render() {
    const { id } = this.props;

    window.onload = function() {
      var input = document.getElementById("search-input");
      input.addEventListener("keyup", function(event) {
        if (event.keyCode === 13) {
          event.preventDefault();
          document.getElementById("mySearchBtn").click();
        }
      });

    };

    return (
      <React.Fragment>
        <form id={id}>
          <div className="search-container">
            <div className="input-group">
              <input
                type="text"
                id="search-input"
                className="search-input form-control"
                placeholder="Search lessons"
                onChange={this.handleChange}
              />
            </div>
            <div>
              <button id="mySearchBtn" onClick={this.handleSearch} />
            </div>
          </div>
        </form>
      </React.Fragment>
    );
  }
}

Search.propTypes = {
  onChange: PropTypes.func,
  onSearch: PropTypes.func,
  id: PropTypes.number
};

export default Search;

Компонент Navbar

import React from "react";
import PropTypes from "prop-types";
import Search from "../../components/courses/Search";

export const LoggedInNavBar = ({ handleSearch, handleSearchChange}) => {
  return (
    <div className="row bobo-menu">
      <div className="col-sm">
        <div className="logo-container">
          <a href={"/courses"}>
            <h1 id="logo" className="hidden">
              TUTORIALS
            </h1>
          </a>
        </div>
      </div>

      <div className="col-sm">
        <Search onSearch={handleSearch} onChange={handleSearchChange} />
      </div>

      <div className="col-sm">
        <p id="motto">
          TUTORIALS<span className="text-succes"> AND</span> LEARNING{" "}
          <span className="text-succes">FOR ALL</span>
        </p>
      </div>

      <div className="col-sm">
        <div className="row row__menu__icons">
          <div className="col-lg-3 col-md-3 col-sm-3">
            <a
              id="title"
              href="/create"
              className="btn btn-login "
              data-mode="signin"
            >
              {" "}
              <i className="fas fa-plus" />
            </a>
          </div>
          <div className="col-lg-3 col-md-3 col-sm-3">
            <a
              id="title"
              href="/create"
              className="btn btn-login "
              data-mode="signin"
            >
              <i className="far fa-user" />
            </a>
          </div>
          <div className="col-lg-3 col-md-3 col-sm-3">
            <a
              id="title"
              href="/me/stories"
              className="btn btn-login "
              data-mode="signin"
            >
              <i className="fas fa-book" />
            </a>
          </div>
          <div className="col-lg-3 col-md-3 col-sm-3">
            <a
              id="title"
              href="/create"
              className="btn btn-login "
              data-mode="signin"
            >
              <i className="fas fa-sign-out-alt" />
            </a>
          </div>
        </div>
      </div>
      <br />
      <br />
    </div>
  );
};

LoggedInNavBar.propTypes = {
  handleSearch: PropTypes.func,
  handleSearchChange: PropTypes.func
};

Компонент курсов

import React, { Fragment } from "react";
import { details } from "../../routes/protectedRoutes";
import { AUTHENTICATED } from "../../utils/myHeaders";
import { ViewAllCourses } from "../../views/courses/viewSearchResults";
import { retrieveAllCourses } from "../../actions/courseActions/courseAction";
import { LoggedInNavBar } from "../navigation/LoggedIn";
import { API_URLS } from "../../appUrls";
import PropTypes from "prop-types";
import { connect } from "react-redux";

export class Courses extends React.Component {
  constructor(props) {
    super(props);
    this.user = details(AUTHENTICATED);
    this.state = {
      search: ""
    };
  }

  componentDidMount() {
    this.fetchCourses();
  }

  fetchCourses = (searchStr = null) => {
    let Url = API_URLS.FETCH_CREATE_ARTICLES;
    const { search } = this.state;
    const query = searchStr !== null ? searchStr : search;
    this.props.dispatch(retrieveAllCourses( Url, query ));
  };

  handleSearch = search => {
    this.setState({ search });
    this.fetchCourses(search);
  };

  handleSearchChange = search => {

    if (!search) {
      this.setState({ search });
      this.fetchCourses(search);
    }
  };

  render() {
    const { allCourses } = this.props;


    return (
        <div>

        <LoggedInNavBar
          handleSearchChange={this.handleSearchChange}
          handleSearch={this.handleSearch}
        />

        <ViewAllCourses results={allVideos} />
        </div>

    );

  }
}

Courses.propTypes = {
  dispatch: PropTypes.func.isRequired,
  allCourses: PropTypes.array
};

const mapStateToProps = state => ({
  allCourses: state.coursesReducer.courses
});
const mapDispatchToProps = dispatch => ({ dispatch });

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Courses);

Ответ API enter image description here

1 Ответ

1 голос
/ 19 мая 2019
  1. Почему в своем редукторе вы объединяете его с результатами предыдущего состояния?Ваша фильтрация никогда не будет показывать связанные данные, если вы делаете это.

  2. Я не вижу payload.results в вашей рассылке действий.Разве это не должно быть action.payload, а не action.payload.results?

return {
  ...state,
  courses: action.payload,
}

В вашем редукторе нет переменной состояния с именем videos.Вы отправляете и храните courses, поэтому вы должны слушать:

const mapStateToProps = state => ({
  allCourses: state.coursesReducer.courses
});

Надеюсь, что это полезно!

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