React Redux - передача аргументов в обработчик событий не работает - PullRequest
0 голосов
/ 13 марта 2019

Хорошо, у меня есть скребок для головы, с которым мне нужно немного помочь. Установка заключается в том, что у меня есть приложение React / Redux со страницей категорий, которая читает список категорий из API, а затем выводит их список. Эта часть отлично работает. Я пытаюсь передать обработчик событий каждому дочернему компоненту категории, который при нажатии отправляет действие, которое переключает состояние компонента, т. Е. Если категория выбрана и нажата, она будет " снимите флажок «it» (что фактически означает удаление записи из таблицы базы данных с именем user_category) и, если она не выбрана, «выберет» эту категорию для этого пользователя (добавьте запись в таблицу user_category).

Итак, у меня есть обработчик onclick (handleCatClick), который должен в конечном итоге передавать categoryId и userId для выполнения этих операций. К сожалению, я обнаружил, что, хотя эти аргументы передаются функции, они в конечном итоге не определены. Поэтому я не уверен, правильно ли я передаю эту функцию или что именно пропустил.

Все работает, кроме этого - может быть, вы можете помочь мне определить проблему; -)

Нажмите здесь, чтобы посмотреть макет базы данных

Нажмите здесь, чтобы посмотреть, как выглядит страница категории

Применимые страницы в моем приложении:

Архитектура выглядит в основном так:

/views/[Categories]
  - index.js (wrapper for the Categories Component)
  - CategoriesComponent.jsx (should be self-explanatory)
   [duck]
        - index.js   (just imports a couple of files & ties stuff together)
        - operations.js  (where my handleCatClick() method is)
        - types.js  (Redux constants)
        - actions.js  (Redux actions)
        - reducers.js   (Redux reducers)
   [components]
        [Category]
                 - index.jsx  (the individual Category component)

/ views / index.js (оболочка главной страницы категории)

import { connect } from 'react-redux';
import CategoriesComponent from './CategoriesComponent';
import { categoriesOperations } from './duck'; // operations.js



const mapStateToProps = state => {
    // current state properties passed down to LoginComponent (LoginComponent.js)
    const { categoryArray } = state.categories;
    return { categoryArray }
  };



  const mapDispatchToProps = (dispatch) => {
    // all passed in from LoginOperations (operations.js)
    const loadUserCategories = () => dispatch(categoriesOperations.loadUserCategories());
    const handleCatClick = () => dispatch(categoriesOperations.handleCatClick());
    return {
        loadUserCategories,
        handleCatClick
    }
  };


  const CategoriesContainer = connect(mapStateToProps,mapDispatchToProps)(CategoriesComponent);

  export default CategoriesContainer;

/ views / CategoriesComponent.jsx (слой отображения для представления Categories)

import React from 'react';
import {Row,Col,Container, Form, Button} from 'react-bootstrap';
import {Link} from 'react-router-dom';
import './styles.scss';
import Category from './components/Category';
import shortid from 'shortid';

class CategoriesComponent extends React.Component {
    constructor(props) {
        super(props);
        this.loadUserCats = this.props.loadUserCategories;
        this.handleCatClick = this.props.handleCatClick;
    }

    componentWillMount() {
        this.loadUserCats();
    }

    render() {
        return (
            <Container fluid className="categories nopadding">
                <Row>
                    <Col xs={12}>
                    <div className="page-container">
                        <div className="title-container">
                            <h4>Pick your favorite categories to contine</h4>
                        </div>
                        <div className="content-container">
                            <div className="category-container">
                                {
                                    this.props.categoryArray.map((item) => {
                                        return <Category className="category" handleClick={this.props.handleCatClick} key={shortid.generate()} categoryData={item} />
                                    })
                                }
                            </div>
                        </div>
                    </div>
                    </Col>
                </Row>
            </Container>
        )        
    }
}


export default CategoriesComponent

/ views / Categories / components / index.jsx (отдельный компонент категории)

import React from 'react';
import {Row,Col,Container, Form, Button} from 'react-bootstrap';
import './styles.scss';
import Img from 'react-image';

class Category extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            categoryName: this.props.categoryData.category_name,
            categoryImg: this.props.categoryData.category_img,
            categoryId: this.props.categoryData.category_id,
            userId: this.props.categoryData.user_id,
            selected: this.props.categoryData.user_id !== null,
            hoverState: ''
        }
        this.hover = this.hover.bind(this);
        this.hoverOff = this.hoverOff.bind(this);
        this.toggleCat = this.toggleCat.bind(this);
    }


    toggleCat() {

        // the onClick handler that is supposed to 
        // pass categoryId and userId.  When I do a 
        // console.log(categoryId, userId) these two values
        // show up no problem...

        const {categoryId, userId} = this.state;
        this.props.handleClick(categoryId, userId);
    }


    hover() {
        this.setState({
            hoverState: 'hover-on'
        });
    }

    hoverOff() {
        this.setState({
            hoverState: ''
        });
    }

    render() {
        const isSelected = (baseCat) => {
            if(this.state.selected) {
                return baseCat + " selected";
            }
            return baseCat;
        }
        return (
            <div className={"category" + ' ' + this.state.hoverState} onClick={this.toggleCat} onMouseOver={this.hover} onMouseOut={this.hoverOff}>
                <div className={this.state.selected ? "category-img selected" : "category-img"}>
                    <Img src={"/public/images/category/" + this.state.categoryImg} className="img-fluid" />
                </div>
                <div className="category-title">
                    <h5 className={this.state.selected ? "bg-primary" : "bg-secondary"}>{this.state.categoryName}</h5>
                </div>
            </div>
        );
    }
}
export default Category;

/ views / Categories / duck / operations.js (где я все это связываю)

// operations.js
import fetch from 'cross-fetch';
import Actions from './actions';
import Config from '../../../../config';


const loadCategories = Actions.loadCats;
const selectCat = Actions.selectCat;
const unSelectCat = Actions.unSelectCat;

const localState = JSON.parse(localStorage.getItem('state'));
const userId = localState != null ? localState.userSession.userId : -1;



const loadUserCategories = () => {

        return dispatch => {
            return fetch(Config.API_ROOT + 'usercategories/' + userId)
            .then(response => response.json())
            .then(json => {
            dispatch(loadCategories(json));
            });
        }      
}


const handleCatClick = (categoryId, categoryUserId) => {

    // HERE IS WHERE I'M HAVING A PROBLEM:
    // for whatever reason, categoryId and categoryUserId
    // are undefined here even though I'm passing in the 
    // values in the Category component (see 'toggleCat' method)

    var params = {
        method: categoryUserId !== null ? 'delete' : 'post',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify(
            {
                "category_id": categoryId, 
                user_id: categoryUserId !== null ? categoryUserId : userId
            }
        )
    };

    const toDispatch = categoryUserId !== null ? unSelectCat : selectCat;
    return dispatch => {
        return fetch(Config.API_ROOT + 'usercategories/', params)
        .then(response => response.json())
        .then(json => {
            dispatch(toDispatch(json));
        });
    } 

}

export default {
    loadUserCategories,
    handleCatClick
}

Проблема, с которой я столкнулся:

Так что я думаю, что я либо неправильно ссылаюсь на handleCatClick, либо я почему-то неправильно передаю categoryId и userId, чтобы, когда он наконец достигнет handleCatClick (categoryId, categoryUserId) в operations.js , это заканчивается как неопределенное. Это, наверное, что-то простое, но я не могу это заметить. ПРИМЕЧАНИЕ. Я не включил файлы, такие как types.js или redurs.js, потому что они, похоже, выходят за рамки проблемы, но если они вам нужны, пожалуйста, дайте мне знать. Заранее спасибо за помощь!

1 Ответ

0 голосов
/ 13 марта 2019

Попробуйте следующие изменения: Добавьте параметры в эти обработчики

const handleCatClick = (categoryId, categoryUserId) => dispatch(categoriesOperations.handleCatClick(categoryId, categoryUserId));

и

return <Category className="category" handleClick={(categoryId, categoryUserId) => this.props.handleCatClick(categoryId, categoryUserId)} key={shortid.generate()} categoryData={item} />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...