titouancreach / vuejs-redux

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

Usage of methods or actions? #15

Closed moparlakci closed 6 years ago

moparlakci commented 6 years ago

When using vuejs-redux which is more interesting or the right way to do it; 1) having only mapStateToProps and mapDispatchToProps in the 'methods' object, and exporting all my other methods within mapDispatchToProps? 2) using a mix of functions within 'methods'

   export default { 

    data: () => ({ 
        store: store,
    }),
    methods: { 
        onUpdateEditable() {
            console.log('onUpdateEditable  in methods?? '); // here ?
        },
        mapStateToProps(state) { 
            return {
                currentUser: state.currentUser,
                newPost: state.postCrud
            } 
        },
        mapDispatchToProps(dispatch) {   
            return {  
                onUpdateEditable(a,b,c) {
                    console.log('onUpdateEditable in redux actions??');  // or here??
                    console.log(a);
                    console.log(b); 
                    console.log(c); 
                },
                actions: bindActionCreators(PostActions, dispatch)
            }
        }
    },
    components: {
        Provider,
        Editable
     }

   }

The template part

<template>
 <Provider :mapDispatchToProps="mapDispatchToProps" :mapStateToProps="mapStateToProps" :store="store">
    <template slot-scope="{newPost, currentUser, actions, onUpdateEditable}"> 

           <Editable :content="newPost.item.message" :onUpdateEditable="onUpdateEditable"></Editable>

    </template>
</Provider>

moparlakci commented 6 years ago

I also have this error when using functional components, it is actually a really simple component Editable.vue

<template functional>
    <div class="textarea" contenteditable="true" @input="onUpdateEditable($event.target.innerText)">{{content}}</div>
</template>

<script>
    export default {
        props: ['content', 'onUpdateEditable']         
    }
</script>

schermafbeelding 2018-02-09 om 11 18 52

titouancreach commented 6 years ago

Hi,

For the first question, I would advice (this is how I do) that the container component ONLY have mapDispatchToProps, mapStateToProps and the store.

I often use the render function to create this component since he is very simple:

import store from './store.js'
import Provider from 'vuejs-redux';

// Since I don't use the vuejs template, I don't need to put the 2 functions inside my component.
const mapStateToProps = state => ({ 
  currentUser: state.currentUser,
  newPost: state.postCrud
});

const mapDispathToProps = dispatch => ({
  actions: bindActionCreators(PostActions, dispatch)
});

// just an helper function to render to make my main render function lightweight 
const renderEditable = h => ({actions, newPost, currentUser}) => 
  h('Editable', props: {
    content: newPost.item.message,
    actions
  });

// I don't need data neither :)
// The component can become functional, that's the good part!

export default { 
  functional: true,

  components: {
    Provider,
    Editable
  },

  render(h) {
    return h('Provider', {
      props: {
        mapDispatchToProps, 
        mapStateToProps
      },
      scopedSlots: {
        default: renderEditable(h)
      }
    }
  }
}

To sum up, no more than mapDispatchToProps, mapStateToProps and the store in your container component.

Remember that your component can take props from its parent. In your case, you can take the function

export default {
  props: {
    onUpdateEditable: {
      required: true,
      type: function
    }
  }
}

Since you have this function in your parent, you can pass it to your child simply with:

<template>
 <Provider :mapDispatchToProps="mapDispatchToProps" :mapStateToProps="mapStateToProps" :store="store">
    <template slot-scope="{newPost, currentUser, actions}"> 
           <Editable :content="newPost.item.message" :onUpdateEditable="this.onUpdateEditable"><!--
 it comes from the props--></Editable>                    
    </template>
</Provider>

This is now a "vue" problem and not a "vuejs-redux" anymore :)

For the second question, I think the problem if how you access your prop in the template. Functional components have a different way to call the props. Check it out here https://vue-loader.vuejs.org/en/features/functional.html

Good luck

moparlakci commented 6 years ago

So the container component becomes a functional component, not the child in your example?

titouancreach commented 6 years ago

The child can become a functional component too. You component is functional when you have no reference on this. (i.e, no "data" no "methods"). For your child component, use https://vue-loader.vuejs.org/en/features/functional.html

moparlakci commented 6 years ago

Thanks for the explanation, Im a React person, but currently working on a VueJS project, Redux keeps my apps structured.. thanks again for the vuejs-redux binding ;)

titouancreach commented 6 years ago

I'm a React person too. I love Redux and the Flux pattern :)