titouancreach / vuejs-redux

Flexible binding between Vue and Redux
57 stars 11 forks source link

Components 'watch' not firing when props change in store. #18

Closed CraigHarley closed 6 years ago

CraigHarley commented 6 years ago

I think this is because of how redux replaces the whole store each time there is an update, probably knocking out the vue.js getter + setter bindings on the way.

I have a component which passes the prop down to a child, which must watch the prop change and perform some action. However when the prop changes in the parent, the child does not get the new prop.

Is there any way around this? Such as not clobbering the vue getter + setter from object?

titouancreach commented 6 years ago

Hi @CraigHarley I never had any issue with this before. Can you provide me a simple example that reproduces the bug/issue you are describing :) ? Thanks

CraigHarley commented 6 years ago

Thanks for the quick response.

Parent:

<template>
    <div class="row">
        <Child  :info="info"></Child>
    </div>
</template>
<script>
// @flow
import Child from "./Child.vue";

export default {
    props: [
        "info",
         "someAction"
    ],
    components: {
        Child
    }
};

</script>

Child:

<template>
    <div class="columns large-8">
                    <component :is="infoState.componentName"
                               v-bind="infoState.props"
                    >
                    </component>
    </div>
</template>
<script>
    // @flow
    export default {
        props: [
            "info"
        ],
        watch: {
            info(newInfo) {
                console.log('This does not get called when reducer resolves');
                this.infoState= newInfo;
            }
        },
        data() {
            return {
                infoState: []
            };
        }
    };
</script>
import {connect} from "redux-vue";
import {someAction} from "../../actions";

import Parentfrom "./Parent.vue";

function mapStateToProps({layout, types, widgets}) {
    return {
        info
    };
}

function mapDispatchToProps(dispatch) {
    return {
        someAction: (payload) => someAction(dispatch, payload)
    };
}

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

I'm confident that redux is working exactly as it should, I'm seeing what I would expect in the dev tools.

To be frank, I've mostly used redux with react so I might be misunderstanding something about how vue's reactivity works with redux

The actual prop is updated in the parent, it's just that the watch handler is not detecting the change in the child.

CraigHarley commented 6 years ago

What's even weirder is that Child has the correct state in infoState.

But the dynamic component (below) doesn't get updated, the reason I need the watch handler to fire is to get that to update.

                    <component :is="infoState.componentName"
                               v-bind="infoState.props"
                    >
                    </component>
titouancreach commented 6 years ago

I've created a quick example that works: https://codesandbox.io/s/92xq1npkm4 with your example. I can see that the console.log is called as expected. Can you point out to me what is the difference between my example and your code ?

Thanks :)

titouancreach commented 6 years ago
import {connect} from "redux-vue";

You're maybe not in the right github :|  This plugin is called vuejs-redux and doesn't expose the "connect" method

You definitely want to go there: https://github.com/nadimtuhin/redux-vue

CraigHarley commented 6 years ago

How embarrassing. 🤦‍♂️

Thanks for the help.