簡體   English   中英

React Redux-將參數傳遞給事件處理程序不起作用

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

好的,我得到了一個頭部抓癢器,需要一點幫助。 設置是我有帶有類別頁面的React / Redux應用程序,該頁面從API讀取類別列表,然后將它們列出。 那部分工作正常。 我想做的是將事件處理程序傳遞給每個類別子組件,單擊它們時,將分派一個動作以切換組件的狀態,即,如果選擇並單擊了類別,它將“取消選擇”(實際上意味着從名為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(“類別”視圖的顯示層)

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,以便當它最終到達operations.js中的handleCatClick(categoryId,categoryUserId)時 ,它最終未定義。 這可能很簡單,但我找不到它。 注意:我沒有包含types.js或reducers.js之類的文件,因為它們似乎不在問題范圍內,但是如果您需要它們,請告訴我。 在此先感謝您的幫助!

嘗試以下更改:向這些處理程序添加參數

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} />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM