简体   繁体   English

React Redux-将参数传递给事件处理程序不起作用

[英]React Redux - passing arguments to event handler not working

Ok, I got a head scratcher I need a little bit of help with. 好的,我得到了一个头部抓痒器,需要一点帮助。 The setup is that I have React/Redux app with a Categories page that reads a list of categories from an API, then lists them out. 设置是我有带有类别页面的React / Redux应用程序,该页面从API读取类别列表,然后将它们列出。 That part works fine. 那部分工作正常。 What I'm trying to do is pass in an event handler to each of the category child components that, when clicked, dispatches an action that toggles the state of the component, ie, if the category is selected and clicked on, it will "unselect" it (which actually means deleting an entry from a database table called user_category), and if not selected, will "select" that category for that user (add an entry in the user_category table). 我想做的是将事件处理程序传递给每个类别子组件,单击它们时,将分派一个动作以切换组件的状态,即,如果选择并单击了类别,它将“取消选择”(实际上意味着从名为user_category的数据库表中删除一个条目),如果未选中,将为该用户“选择”该类别(在user_category表中添加一个条目)。

So I've got an onclick handler (handleCatClick) that is supposed to ultimately pass a categoryId and a userId to perform these operations. 因此,我有一个onclick处理程序(handleCatClick),该处理程序最终应该传递categoryId和userId来执行这些操作。 Unfortunately what I'm finding that even though these arguments are being passed to the function, they end up being undefined. 不幸的是,我发现即使将这些参数传递给函数,它们最终仍未定义。 So I'm not sure if I'm passing this function correctly or what exactly I've missed. 因此,我不确定是否正确传递了此函数,或者我错过了什么。

Everything works other than this - maybe you can help me spot the problem ;-) 除此之外,其他所有方法都可以正常工作-也许您可以帮助我发现问题;-)

Click here to view the database layout 单击此处查看数据库布局

Click here to see how the category page looks 单击此处查看类别页面的外观

The applicable pages in my app: 我的应用中的适用页面:

The architecture looks basically like this: 该架构基本上如下所示:

/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(main Category page wrapper) /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 (display layer for the Categories view) /views/CategoriesComponent.jsx(“类别”视图的显示层)

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 (Single Category Component) /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 (where I tie it all together) /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
}

The problem that I am having: 我遇到的问题是:

So I'm thinking I'm either not referencing handleCatClick correctly, or I'm somehow not passing the categoryId and userId correctly so that when it finally gets to handleCatClick(categoryId, categoryUserId) in operations.js , it ends up as undefined. 所以我想我要么没有正确地引用handleCatClick,要么就是某种程度上没有正确地传递categoryId和userId,以便当它最终到达operations.js中的handleCatClick(categoryId,categoryUserId)时 ,它最终未定义。 It's probably something simple but I can't spot it. 这可能很简单,但我找不到它。 NOTE: I haven't included files like the types.js or reducers.js, because they seem to be outside the scope of the problem, but if you need them please let me know. 注意:我没有包含types.js或reducers.js之类的文件,因为它们似乎不在问题范围内,但是如果您需要它们,请告诉我。 Thanks in advance for your help! 在此先感谢您的帮助!

Try this changes: Add params to these handlers 尝试以下更改:向这些处理程序添加参数

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

and

return <Category className="category" handleClick={(categoryId, categoryUserId) => this.props.handleCatClick(categoryId, categoryUserId)} key={shortid.generate()} categoryData={item} />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM