【问题标题】:React/Redux - mapDispatchToProps. Props undefinedReact/Redux - mapDispatchToProps。道具未定义
【发布时间】:2021-06-06 19:20:09
【问题描述】:

我正在数据库中查找具有反应的应用程序中的信息。在 actions.js 文件中,我可以看到 response.data 数据,当我放置一个 console.table 时。

但即使导出,当我尝试显示信息时,变量的值也是未定义的。

我已经查看了我用来学习的原始文件,但我看不出错误在哪里。

action.js

import { CLEAR_SEARCH, SEARCH_CUSTOMERS } from "./actionTypes";

import Axios from "axios";
import { SEARCH_CUSTOMERS_URL } from "../../configs";

export const searchCustomers = (lat, lng, query) => dispatch => {
    Axios.post(SEARCH_CUSTOMERS_URL, {
        q: query,
    })
    .then(response => {
            const customers = response.data;
            
            console.log( "services/searchCustomers/actions.js, line 30" );
            console.log( customers ); //ok, showing data
        
            return dispatch({ type: SEARCH_CUSTOMERS, payload: customers });
        })
        .catch(function(error) {
            console.log(error);
        });
};

export const clearSearch = () => dispatch => {
    const customers = [];
    return dispatch({ type: CLEAR_SEARCH, payload: customers });
};

reducer.js

import { CLEAR_SEARCH, SEARCH_CUSTOMERS } from "./actionTypes";

const initialState = {
    customers: []
};

export default function(state = initialState, action) {
    switch (action.type) {
        case SEARCH_CUSTOMERS:
            return { ...state, customers: action.payload };

        case CLEAR_SEARCH:
            return { ...state, customers: action.payload };
        default:
            return state;
    }
}

actionTypes.js

export const SEARCH_CUSTOMERS = "SEARCH_CUSTOMERS";
export const CLEAR_SEARCH = "CLEAR_SEARCH";

index.js

import React, { Component } from "react";
import { clearSearch, searchCustomers } from "../../../../services/searchCustomers/actions";

import Dialog from "@material-ui/core/Dialog";
import DelayLink from "../../../helpers/delayLink";
import Ink from "react-ink";
import LazyLoad from "react-lazyload";
import { Redirect } from "react-router";

import CustomerSearch from "../../CustomerSearch";
import CustomerSearchList from "../CustomerSearchList";

import { connect } from "react-redux";
import { debounce } from "../../../helpers/debounce";
import ContentLoader from "react-content-loader";

class SelectCustomer extends Component {
    state = {
        open: false,
        queryLengthError: false,
        loading: false,
        showBgImage: true,
        nothingFound: false,
    };

    handleCustomerSearch = debounce((query) => {
        // call to searchCustomers search API
        if (query.length >= 3) {            
            this.props.searchCustomers(
                JSON.parse(localStorage.getItem("userSetAddress")).lat,
                JSON.parse(localStorage.getItem("userSetAddress")).lng,
                query
            );  
            
            console.table( this.props ); //customers is undefined
            
            this.setState({
                queryLengthError: false,
                loading: true,
                nothingFound: false,
            });
        } else {
            this.setState({ queryLengthError: true });
        }       
    }, 400);

    componentDidMount() {
        //others
    }
    componentWillUnmount() {
        //others
    }

    componentWillReceiveProps(nextProps) {      
        //this.props.customers is undefined
        if (this.props.customers !== nextProps.customers) {
            this.setState({ loading: false });
        }
        
        // console.log(nextProps.customers.length);

        if (nextProps.customers) {
            if (nextProps.customers.length === 0 ) {
                this.setState({ showBgImage: true, nothingFound: true });
            } else {
                this.setState({ showBgImage: false, nothingFound: false });
            }
        }
        
        //Overlay/Dialog.
        if (nextProps.confirmSelectCustomerOpen === false) {
            this.setState({ open: false });
        }
        if (nextProps.confirmSelectCustomerOpen === true) {
            this.setState({ open: true });
        }
    }
    
    //Overlay/Dialog
    handleClose = () => {
        this.setState({ open: false });
    };
    
    render() {  
                
        return (
            <React.Fragment>                
                <Dialog
                    fullWidth={true}
                    fullScreen={false}
                    open={this.state.open}
                    onClose={this.handleClose}
                    style={{ width: "100%", margin: "auto" }}
                    PaperProps={{ style: { backgroundColor: "#fff", borderRadius: "10px" } }}
                >       
                
                {this.state.queryLengthError && (
                    <div className="auth-error" style={{ marginBottom: "4rem" }}>
                        <div className="">{localStorage.getItem("searchAtleastThreeCharsMsg")}</div>
                    </div>
                )}
                
                
                <CustomerSearch searchFunction={this.handleCustomerSearch} />
                
                
                {this.state.loading && (
                    {/*loading*/}
                )}
                
                
                {/* Here Should list customers */}              
                {this.props.customers && this.props.customers.length > 0 && (
                    <CustomerSearchList customers={this.props.customers} />
                )}
                
                
                {this.state.showBgImage && (
                    <div className="d-flex justify-content-center mt-100">
                        <img
                            className="img-fluid explore-bg"
                            src="/assets/img/various/explore-bg.png"
                            alt={localStorage.getItem("restaurantSearchPlaceholder")}
                        />
                    </div>
                )}
                {this.state.nothingFound && (
                    <div className="auth-error" style={{ marginBottom: "4rem" }}>
                        <div className="error-shake">{localStorage.getItem("exploreNoResults")}</div>
                    </div>
                )}

                </Dialog>
            </React.Fragment>
        );
    }
}

const mapStateToProps = (state) => ({
    customers: state.customers  
});

export default connect(
    mapStateToProps,
    { searchCustomers, clearSearch }
)(SelectCustomer);

CustomerSearch/index.js

import React, { Component } from "react";

import Ink from "react-ink";

class CustomerSearch extends Component {
    state = {
        customer: ""
    };
    componentDidMount() {
        this.searchInput.focus();
    }
    static contextTypes = {
        router: () => null
    };

    handleInputChange = e => {
        this.setState({ customer: e.target.value });
        this.props.searchFunction(e.target.value);
    };

    render() {
        return (
            <React.Fragment>
                <div className="col-12 p-0">
                    <div className="block m-0">
                        <div className="block-content p-0">
                            <div className="input-group search-box">
                                <div className="input-group-prepend">
                                    <button
                                        type="button"
                                        className="btn search-navs-btns"
                                        style={{ position: "relative" }}
                                        onClick={this.context.router.history.goBack}
                                    >
                                        <i className="si si-arrow-left" />
                                        <Ink duration="500" />
                                    </button>
                                </div>
                                
                                {/*
                                placeholder do input
                                {localStorage.getItem("restaurantSearchPlaceholder")}
                                */}
                                <input
                                    type="text"
                                    className="form-control search-input"
                                    placeholder="Pesquisar Cliente"
                                    value={this.state.customer}
                                    onChange={this.handleInputChange}
                                    ref={input => {
                                        this.searchInput = input;
                                    }}
                                />

                                <div className="input-group-append">
                                    <button type="submit" className="btn search-navs-btns" style={{ position: "relative" }}>
                                        <i className="si si-magnifier" />
                                        <Ink duration="500" />
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </React.Fragment>
        );
    }
}

export default CustomerSearch;

CustomerSearchList/index.js

import React, { Component } from "react";

import DelayLink from "../../../helpers/delayLink";
import Ink from "react-ink";
import LazyLoad from "react-lazyload";

class CustomerSearchList extends Component {
    render() {
        const { customers } = this.props;

        return (
            <React.Fragment>
                
                    {customers.map((customer) => (
                        <div key={customer.id} className="col-xs-12">
                            <DelayLink
                                to={"../stores/" + customer.id}
                                delay={200}
                                className="block block-link-shadow text-center light-bottom-border"
                            >
                                <Ink duration="500" />
                            </DelayLink>
                        </div>
                    ))}
                
            </React.Fragment>
        );
    }
}

export default CustomerSearchList;

reducers.js

import { combineReducers } from "redux";

.... …… 从“./searchCustomers/reducer”导入customerSearchReducer; 从“./addresses/reducer”导入addressesReducer; …… ....

export default combineReducers({
    ...
    customers: customerSearchReducer,
    addresses: addressesReducer,
    ...
});

SEARCH_CUSTOMERS_URL - php 的 URL,获取数据:

$response = ['customers' => $customers];

Output customers: Array(3)
0: {id: 2, name: "Customer 1", email: "customer1@gmail.com"}
1: {id: 3, name: "Customer 2", email: "customer2@gmail.com"}
2: {id: 4, name: "Customer 3", email: "customer3@gmail.com"}

3 天绞尽脑汁。我做了一些研究,但我无法解决问题。我是反应/减少的新手,并试图根据这个脚本弄清楚。

【问题讨论】:

  • 你使用的是 redux-thunk 还是其他中间件?
  • 能否请您添加console.log( customers ); //ok, showing data 的截图?只是为了查看您获得的数据。
  • Steve Bunting:在另一个当前未使用的系统文件中,有这个导入:import thunk from "redux-thunk";
  • 你的 rootReducer 是什么样子的?

标签: reactjs reduce


【解决方案1】:

根据 cmets...将 searchCustomer reducer 添加到 rootReducer。

【讨论】:

    猜你喜欢
    • 2018-06-01
    • 2018-01-09
    • 2018-11-12
    • 2018-04-05
    • 1970-01-01
    • 2016-11-08
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多