Повторно визуализируйте компонент с новыми данными, не имея локального состояния в React. - PullRequest
0 голосов
/ 03 октября 2018

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

Вот мои настройки маршрутов в файле App.js ...

class App extends Component {
    async componentDidMount() {
        try {
            await this.props.asyncLoadBooks();
            await this.props.asyncLoadCategories();
        } catch (error) {
            console.log(error);
        }
    }

    render() {
        return (
            <>
                <Header />
                <div className="global-wrapper">
                    <div className="container">
                        <aside className="side-bar">
                            <Categories />
                        </aside>

                        <main className="main-content">
                            <Switch>
                                <Route exact path="/" component={Books} />
                                <Route
                                    exact
                                    path="/category/:id"
                                    component={Category}
                                />
                                <Route component={NotFound} />
                            </Switch>
                        </main>
                    </div>
                </div>
            </>
        );
    }
}

InApp.js, как вы можете видеть, я загружаю данные через локальный файл JSON с axios в Actions файлах booksActions и categoriesAction, это довольно просто.

И вотКомпонент категорий ...

class Categories extends Component {
    render() {
        const { categories } = this.props;

        let categoriesList;

        if (categories && categories.length !== 0) {
            categoriesList = categories.map(category => (
                <li key={category.id}>
                    <Link to={`/category/${category.id}`}>{category.name}</Link>
                </li>
            ));
        } else {
            categoriesList = <Loading />;
        }
        return (
            <div>
                <h2>Categories</h2>
                <ul>{categoriesList}</ul>
            </div>
        );
    }
}

const mapState = state => ({
    categories: state.categories.categories
});

export default connect(mapState)(Categories);

И я запускаю еще одно действие в ComponentDidMount() одного компонента категории, чтобы получить все книги, связанные с этим компонентом, и отобразить их ...

class Category extends Component {
    componentDidMount() {
        this.props.getCategoryBooks(this.props.match.params.id);
    }

    componentDidUpdate(prevProps) {
        if (prevProps.match.params.id !== this.props.match.params.id) {
            this.props.getCategoryBooks(this.props.match.params.id);
        }
    }

    render() {
        const { categoryBooks } = this.props;
        return (
            <div>
                {/* <h1>{this.props.match.params.id}</h1> */}
                {categoryBooks &&
                    categoryBooks.map(book => {
                        return <div key={book.id}>{book.title}</div>;
                    })}
            </div>
        );
    }
}

const mapState = state => ({
    categories: state.categories.categories,
    categoryBooks: state.books.categoryBooks
});

const mapActions = {
    getCategoryBooks
};

export default connect(
    mapState,
    mapActions
)(Category);

Теперь все работает в первый раз, однако, когда я нажимаю на другую категорию, компонент <Category /> не обновляется, потому что я отправляю действие в componentDidMount(), таким образом, tКомпонент уже смонтирован в первый раз, поэтому он не отправляет действие снова после того, как я нажму на другую категорию, теперь, каков наилучший способ справиться с этим?

Второй вопрос, где я нахожусь наКатегория route http://localhost:3000/category/9967c77a-1da5-4d69-b6a9-014ca20abd61 и я пытаюсь обновить страницу, список категорий загружается нормально на боковой панели, но отдельный компонент отображается пустым, и когда я смотрю на redux-devtools, я обнаруживаю, что действие GET_CATEGORY_BOOKS запускается до того, какLOAD_BOOKS и LOAD_CATEGORIES в файле App.js, потому что дочерний метод componentDidMount() вызывается перед его родительским эквивалентным методом.Как это тоже решить?

Надеюсь, вы, ребята, можете мне помочь в этом.

Редактировать

Как заметил @@ NguyễnThanhTú, в компонентеDidupate была опечатка, теперь онаработает при нажатии на другую категорию.Это оставляет нас со второй проблемой при перезагрузке страницы в маршрут категории, и данные не отображаются из-за запуска App.js componentDidMount после его дочерних компонентов.

Edit

Вотрепо на Github для этого проекта ... https://github.com/Shaker-Hamdi/books-app

1 Ответ

0 голосов
/ 03 октября 2018

В вашем booksActions.js добавьте:

export const getCategoryBooksV2 = categoryId => {
    return async (dispatch, getState) => {
        const { books } = getState();
        if (books.books.length === 0) {
            console.log('Only executing once')  // testing purpose only
            const response = await axios.get("books.json");
            const data = response.data.books;
            dispatch(loadBooks(data));
            dispatch(getCategoryBooks(categoryId));
        }
        dispatch(getCategoryBooks(categoryId));
    };
};

В вашем Category.js используйте нового создателя действий:

import { getCategoryBooksV2 } from "../books/booksActions";
...
componentDidMount() {
    this.props.getCategoryBooksV2(this.props.match.params.id);
}
...
const mapActions = {
    getCategoryBooksV2
};

Это решение вдохновлено этим примером:

function incrementIfOdd() {
  return (dispatch, getState) => {
    const { counter } = getState();

    if (counter % 2 === 0) {
      return;
    }

    dispatch(increment());
  };
}

Из Документация Redux-Thunk

Это демо:

enter image description here

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