简体   繁体   中英

Updating redux state onClick

I have a component that displays data from the state. I'm using redux for state. I want to be able to click a button and filter the state. But I'm stuck on dispatching the action from the button.

Right now I have a button that is supposed to dispatch the action but it's not being called. I'm not sure if the mapsToDispatchProps is wrong or it's something else.

Here is the actions

import { GET_POLLS, SHOW_APPROVAL } from './types';


const URL = 'https://projects.fivethirtyeight.com/polls/polls.json';

export const getPolls = () => dispatch => {

    return fetch(URL)
        .then(res => res.json())
        .then(polls => {
            dispatch({ type: GET_POLLS, payload: polls })
        })


}

export const getApproval = () => ({ type: SHOW_APPROVAL }) 

reducer

import {
    GET_POLLS,
    SHOW_APPROVAL
} from '../actions/types';



const pollReducer = (state = [], { type, payload }) => {
    switch (type) {
        case GET_POLLS:
            return payload
        case SHOW_APPROVAL:
            return (payload.type === "trump-approval")
        default:
            return state
    }
}

export default pollReducer;

types

export const GET_POLLS = 'GET_POLLS';
export const POLLS_LOADING = 'POLLS_LOADING';
export const SHOW_ALL = 'SHOW_ALL';
export const SHOW_APPROVAL = 'SHOW_APPROVAL';

list that displays data

import React, { Component } from 'react'
import { PollCard } from '../Components/PollCard'
// import FilterLink from './FilterLink'
import * as moment from 'moment';

import { connect } from 'react-redux'
import { getPolls, getApproval } from '../actions/index';

class PollList extends Component {

    componentDidMount() {
        this.props.getPolls();
    }



    render() {


        console.log("rendering list")
        const { polls } = this.props

        const range = 30
        var dateRange = moment().subtract(range, 'days').calendar();
        var filteredPolls = polls.filter(e => Date.parse(e.endDate) >= Date.parse(dateRange)).reverse()



        return (

            <React.Fragment>
                <button onClick={getApproval}>
                    Get Approval

                </button>
                {console.log("get approval", getApproval)}


                {
                    filteredPolls && filteredPolls.map((poll) => (
                        <div key={poll.id}>
                            <PollCard poll={poll} />

                            {/* {(poll.type)} */}

                        </div>
                    ))




                }
            </React.Fragment>

        )
    }
}

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

const mapDispatchToProps = {
    getApproval
};

export default connect(
    mapStateToProps,
    mapDispatchToProps,
    { getPolls, getApproval }
)(PollList);


// export default PollList;

Your mapDispatchToProps() appears to be configured incorrectly. You need to define a function that returns an object , defining a key-value pair for each action you want to make available as a prop in your component.

const mapDispatchToProps = (dispatch) => {
   return {
      getApproval: () => {
         dispatch(getApproval())
      },
      getPolls: () => {
         dispatch(getPolls())
      }
   }
}

export default connect(
    mapStateToProps,
    mapDispatchToProp)(PollList);

Now getPolls is available as prop and you can use it in componentDidMount()

componentDidMount() {
    this.props.getPolls();
}

You should also create an onClick handler for your getApproval action

handleClick = () => {
   this.props.getApproval()
}

And then connect it to your onClick event-listener

<React.Fragment>
    <button onClick={this.handleClick}>
        Get Approval
    </button>
    console.log("get approval", getApproval)}
    {
        filteredPolls && filteredPolls.map((poll) => (
           <div key={poll.id}>
              <PollCard poll={poll} />
                 {/* {(poll.type)} */}
           </div>
        ))
    }
</React.Fragment>

Action File

export const getPolls = () => dispatch => {
      fetch(URL)
        .then(res => res.json())
        .then(polls => {
            dispatch({ type: GET_POLLS, payload: polls })
        })
        .catch(errors => {
            dispatch({ type: "GET_ERRORS", payload: errors.response.data })
        })
}

Reducer

import {
    GET_POLLS,
    SHOW_APPROVAL
} from '../actions/types';

const pollReducer = (state = [], { type, payload }) => {
    switch (type) {
        case GET_POLLS:
            return payload
        case SHOW_APPROVAL:
            return state.filter((poll) => {
                return poll.type === "trump-approval"
            })
        case "GET_ERRORS":
            return payload
        default:
            return state
    }
}

export default pollReducer;

You are not calling the action function.

// Either destructure it
const { polls, getApproval } = this.props;
<button onClick={getApproval}>
    Get Approval
</button>
// Or use this.props.function
<button onClick={this.props.getApproval}>
    Get Approval
</button>
// You don't need this
const mapDispatchToProps = {
    getApproval
};
// You don't need this

const mapStateToProps = state => {
    return {polls: state.polls};
};
export default connect(
    mapStateToProps,
    // Doing this is easier, cleaner & faster
    { getPolls, getApproval }
)(PollList);

Here you are doing it correctly;

componentDidMount() {
    this.props.getPolls();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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