简体   繁体   中英

Props not being updated when Redux action is called

Just a disclaimer - my code worked when I had problematic function in my main component. After I exported it it stopped behaving as it should. My theory is because somehow props are not being updated properly.

Anyway, I have a component, which after it's clicked it starts listening on window object and sets proper store element to "true" and depending on next object clicked acts accordingly. After incorrect object is clicked, the store should revert to false, and it does, however the props are still "true" as shown on the screenshot below.

How can I solve this? Perhaps there is a way that function could take store as parameter instead of props? Or im calling actions inproperly or im missing something completely?

Code below:

Main component (relevant parts?):

import React from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'

import {activate} from '../../actions/inventory'
import { setModalContent, setModalState } from '../../actions/modal';
import inventoryReducer from '../../reducers/inventory';

import {chainMechanics} from './itemMechanics/chainMechanics';


class ItemRenderer extends React.Component{

    handleBoltcuttersClicked(){
        this.props.activate('boltcutters', true);
        setTimeout(() => chainMechanics(this.props), 100)
    }

    inventoryItemRender(){
        let inventoryItem = null;
        if(this.props.inventory.items.boltcutters){
            inventoryItem = <a className={this.props.inventory.activeItem.boltcutters ? "ghost-button items active " : "ghost-button items"} href="#" id='boltcuttersId' onClick={() => this.handleBoltcuttersClicked()}>Boltcutters</a>
        }
        return inventoryItem;
    }

    render(){
        let renderItems = this.inventoryItemRender();
        return(
            <div>
                {renderItems}
            </div>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        level: state.level,
        inventory: state.inventory
    }
}

function mapDispatchToProps(dispatch) {
    //dispatch w propsach
    return(
        bindActionCreators({activate: activate, setModalState: setModalState, setModalContent: setModalContent }, dispatch)
    ) 
  }

export default connect(mapStateToProps, mapDispatchToProps)(ItemRenderer);

File with problematic function:

import {activate} from '../../../actions/inventory'
import { setModalContent, setModalState } from '../../../actions/modal';

export function chainMechanics(props){
    let clickedElement;
    window.onclick = ((e)=>{
        console.log(clickedElement, 'clickedelement', props.inventory.activeItem.boltcutters)
        if(props.inventory.activeItem.boltcutters===true){
            clickedElement = e.target;
            if(clickedElement.id === 'chainChainedDoor'){
                props.activate('boltcutters', false);
                props.setModalContent('Chain_Broken');
                props.setModalState(true);
            } else if(clickedElement.id === 'boltcuttersId'){
                console.log('foo')
            } else  {
                props.activate('boltcutters', false);
                props.setModalContent('Cant_Use');
                props.setModalState(true);
                console.log("props.inventory.activeItem.boltcutters", props.inventory.activeItem.boltcutters); 
            }
        }
    })
}

My actions:

const inventoryReducer = (state = inventoryDefaultState, action) => {
    switch (action.type) {
        case 'ACTIVE':
            console.log(action)
            return {
                ...state,
                activeItem: {
                    ...state.activeItem,
                    [action.item]: action.isActive
                }
            }
        default:
            return state;
    }
}

How I configure store:

export default () => {
    const store = createStore(
        combineReducers({
            level: levelReducer,
            modal: modalReducer,
            inventory: inventoryReducer,
            styles: stylesReducer
        }),
        applyMiddleware(thunk)
    )
    return store;
}

I believe thats eveyrthing needed? If not please do let me know, I've been trying to make this work for a long time.

Screenshot: 控制台日志

You can use the React's function componentWillReceiveProps . That would trigger a rerender like this (and also make use of next props/state):

componentWillReceiveProps(next) {
    console.log(next);
    this.inventoryItemRender(next);
}

inventoryItemRender(next){
        const inventory = next.inventory ? next.inventory : this.props.inventory;
        let inventoryItem = null;
        if(inventory.items.boltcutters){
            inventoryItem = <a className={inventory.activeItem.boltcutters ? "ghost-button items active " : "ghost-button items"} href="#" id='boltcuttersId' onClick={(next) => this.handleBoltcuttersClicked(next)}>Boltcutters</a>
        }
        return inventoryItem;
}

handleBoltcuttersClicked(props){
        this.props.activate('boltcutters', true);
        setTimeout(() => chainMechanics(props), 100)
    }

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