Uncaught (in promise) ReferenceError: state is not defined

问题描述 投票:0回答:1

出现这样的错误: enter image description here enter image description here

import { createStore } from 'vuex'
import { postModule } from './postModule'

export default createStore({
  
  modules: {
    /* post -  название модуля */
    post: postModule,
  },
})

<!-- component PostModule.js -->
import axios from 'axios'

export const postModule = {
 
  state: () => ({
    posts: [],
    isPostsLoading: false,
    selectedSort: '',
    searchQuery: '',
    page: 1,
    limit: 10,
    totalPages: 0,
    sortOptions: [
      { value: 'title', name: 'По названию' },
      { value: 'body', name: 'По содержанию' },
    ],
  }),
  
  getters: {
    sortedPosts(state) {
      return [...state.posts].sort((post1, post2) =>
        post1[state.selectedSort]?.localeCompare(post2[state.selectedSort])
      )
    },
   
    sortedAndSearchedPosts(state, getter) {
      return getter.sortedPosts.filter((post) =>
        post.title.toLowerCase().includes(state.searchQuery.toLowerCase())
      )
    },
  },
 
  mutations: {
    setPosts(state, posts) {
      state.posts = posts
    },
    // setIsPostsLoading(state, bool) {
    //   state.isPostsLoading = bool
    // },
    setSelectedSort(state, selectedSort) {
      state.selectedSort = selectedSort
    },
    setSearchQuery(state, query) {
      state.searchQuery = query
    },
    setPage(state, page) {
      state.page = page
    },
    setTotalPages(state, totalPages) {
      state.totalPages = totalPages
    },
  },
  
  actions: {
    /* commit - нужен для вызова мутаций, dispatch - для вызова других actions  */
    async fetchPosts({ state, commit }) {
      try {
        commit('setIsPostsLoading', true)
        const res = await axios.get(
          `https://jsonplaceholder.typicode.com/posts`,
          {
            params: {
              _page: state.page,
              _limit: state.limit,
            },
          }
        )
       
        commit(
          'setTotalPages',
          Math.ceil(res.headers['x-total-count'] / state.limit)
        )
        commit('setPosts', res.data)
      } catch (error) {
        console.log(error)
      } finally {
        commit('setIsPostsLoading', false)
      }
    },
   
    async loadMorePosts({ state, commit }) {
      try {
        commit('setPage', state.page + 1)

        const res = await axios.get(
          `https://jsonplaceholder.typicode.com/posts`,
          {
            params: {
              _page: state.page,
              _limit: state.limit,
            },
          }
        )
        commit(
          'setTotalPages',
          Math.ceil(res.headers['x-total-count'] / state.limit)
        )

        /* В этом случае мы посты не перезаписываем, а добавляем в конец массива */
        commit('setPosts', [...state.posts, ...res.data])
      } catch (error) {
        console.log(error)
      }
    },
  },
  namespaced: true,
}

<!-- component PostsPageWithStore.vue -->
<template>
  <div>
    <h1>Страница с постами</h1>
    <!-- <my-input v-focus v-model="searchQuery" placeholder="Поиск..." /> -->
    <div class="app__btns">
      <my-button @click="showDialog">Cоздать пост</my-button>

      <!-- <my-select v-model="selectedSort" :options="sortOptions" /> -->
    </div>
    <my-dialog v-model:show="dialogVisible">
      <post-form @create="createPost" />
    </my-dialog>

    <post-list
      :posts="sortedAndSearchedPosts"
      @remove="removePost"
      v-if="!isPostsLoading"
    />
    <div v-else class="loader">Загрузка...</div>
    <div v-intersection="loadMorePosts" class="observer"></div>
  </div>
</template>

<script>
import PostForm from '@/components/PostForm.vue'
import PostList from '@/components/PostList.vue'

import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
export default {
  
  components: { PostList, PostForm },
  data() {
    return {
      dialogVisible: false,
    }
  },
  
  methods: {
    ...mapMutations({
      setPage: 'post/setPage',
    }),
    ...mapActions({
      loadMorePosts: 'post/loadMorePosts',
      fetchPosts: 'post/fetchPosts',
    }),

    /* мы подписались на это событие и принимаем post из компонента PostForm */
    createPost(post) {
      this.posts.push(post)
      this.dialogVisible = false
    },
    removePost(post) {
      this.posts = this.posts.filter((p) => p.id !== post.id)
    },
    showDialog() {
      this.dialogVisible = true
    },
  },
 
  mounted() {
    this.fetchPosts()
  },

  computed: {
    ...mapState({
      posts: () => state.post.posts,
      isPostsLoading: () => state.post.isPostsLoading,
      selectedSort: () => state.post.selectedSort,
      searchQuery: () => state.post.searchQuery,
      page: () => state.post.page,
      limit: () => state.post.limit,
      totalPages: () => state.post.totalPages,
      sortOptions: () => state.post.sortOptions,
    }),
    ...mapGetters({
      sortedPosts: 'post/sortedPosts',
      sortedAndSearchedPosts: 'post/sortedAndSearchedPosts',
    }),
  },

  watch: {},
}
</script>

<style>
.app__btns {
  margin: 15px 0;
  display: flex;
  justify-content: space-between;
}

.page__wrapper {
  display: flex;
  margin-top: 15px;
}

.page {
  border: 1px solid black;
  padding: 10px;
}

.current-page {
  border: 3px solid teal;
}

.observer {
  height: 30px;
  background: green;
}
</style>

使用 vuex,我意识到由于 postModule.js 组件中的

isPostsLoading: false
状态,应用程序正在中断。我们将这个状态传递给 PostsPageWithStore.vue 组件,如果你注释掉这个状态,那么一切正常。如何解决?

vue.js vuejs3 vuex vue-router
1个回答
0
投票

注意:阅读Vuex主页上的警告

Pinia 是新的默认值
[...] 您可以将其视为具有不同名称的 Vuex5。


mapState
助手内部,
state
不是来自组件上下文。它是函数的参数。命名它
state
是一种可读性约定(您不必保留):

  // ...
  computed: {
    ...mapState({
      posts: (state) => state.post.posts,
      isPostsLoading: (whatever) => whatever.post.isPostsLoading,
      selectedSort: (_) => _.post.selectedSort
      // ...
    })
  },
  // ...

不过,您可能更喜欢这种语法:

  computed: {
    ...mapState('post', [
      'posts', 'isPostsLoading', 'selectedSort', // ...
    ])
  }
  // this.posts is this.$store.state.post.posts
  // this.isPostsLoading is this.$store.state.post.isPostsLoading
  

或者,如果你想将状态属性分配给不同的本地名称:

  computed: {
    ...mapState('post', {
      localNameForPosts: 'posts',
      isLoading: 'isPostsLoading'
      // ...
    })
  }
  // this.localNameForPosts is this.$store.state.post.posts
  // this.isLoading is this.$store.state.post.isPostsLoading

如果您需要,这些语法也可用于

mapGetters
mapActions
。例如:

  computed: {
    ...mapGetters('post', ['sortedPosts', 'sortedAndSearchedPosts']),
  }

相关文档:

© www.soinside.com 2019 - 2024. All rights reserved.