gpt4 book ai didi

javascript - 为什么将状态映射到 props 会给出未定义的结果?

转载 作者:行者123 更新时间:2023-12-01 03:20:24 25 4
gpt4 key购买 nike

我的 Redux 设置有问题。我对 posts 操作和化简器的单个文件没有问题,但是一旦添加了 searchQueries 部分,它就只显示 undefined searchQueries 属性的值。

我已尝试尽可能复制它并针对第二组操作/ reducer 修改它,但在 的情况下我仍然得到 undefined 属性搜索查询。我正在获取所有 Prop ,包括 posts 情况下的默认值。下面是每一个的代码:

/actions/posts.js:

import axios from 'axios'

export function postsHasErrored(bool) {
return {
type: 'POSTS_HAS_ERRORED',
hasErrored: bool
}
}

export function postsIsLoading(bool) {
return {
type: 'POSTS_IS_LOADING',
isLoading: bool
}
}

export function postsFetchDataSuccess(posts) {
return {
type: 'POSTS_FETCH_DATA_SUCCESS',
posts
}
}

export function totalPagesFetchDataSuccess(totalPages) {
return {
type: 'TOTAL_PAGES_FETCH_DATA_SUCCESS',
totalPages
}
}

export function postsFetchData(url) {
return (dispatch) => {
dispatch(postsIsLoading(true))

axios.get(url)
.then(res => {
if (res.status !== 200) throw Error(res.statusText)
dispatch(postsIsLoading(false))
return res
})
.then(res => {
dispatch(postsFetchDataSuccess(res.data))
dispatch(totalPagesFetchDataSuccess(res.headers['x-wp-totalpages']))
})
.catch(() => dispatch(postsHasErrored(true)))
}
}

/actions/searchQueries.js:

const readLocation = (name) => {
let parameter = getParameterByName(name);
if (name === 'categories') {
if (parameter) {
parameter = parameter.split(',')
for (let i = 0; i < parameter.length; i++) parameter[i] = parseInt(parameter[i], 10)
}
else parameter = []
}

if (parameter === null) {
if (name === 'search') parameter = ''
if (name === 'page') parameter = 1
}

console.log(parameter)

return parameter
}

export function setSearchString(searchString) {
return {
type: 'SET_SEARCH_STRING',
searchString
}
}

export function setSearchCategories(searchCategories) {
return {
type: 'SET_SEARCH_CATEGORIES',
searchCategories
}
}

export function setSearchPage(searchPage) {
return {
type: 'SET_SEARCH_PAGE',
searchPage
}
}

export function searchQueriesSetting() {
return (dispatch) => {
dispatch(setSearchString(readLocation('search')))
dispatch(setSearchCategories(readLocation('categories')))
dispatch(setSearchPage(readLocation('page')))
}
}

/reducers/posts.js:

export function postsHasErrored(state = false, action) {
switch (action.type) {
case 'POSTS_HAS_ERRORED':
return action.hasErrored

default:
return state
}
}

export function postsIsLoading(state = false, action) {
switch (action.type) {
case 'POSTS_IS_LOADING':
return action.isLoading

default:
return state
}
}

export function posts(state = [], action) {
switch (action.type) {
case 'POSTS_FETCH_DATA_SUCCESS':
return action.posts

default:
return state
}
}

export function totalPages(state = 1, action) {
switch (action.type) {
case 'TOTAL_PAGES_FETCH_DATA_SUCCESS':
return parseInt(action.totalPages, 10)

default:
return state
}
}

/reducers/searchQueries.js:

export function searchString(state = '', action) {
switch (action.type) {
case 'SET_SEARCH_STRING':
return action.searchString

default:
return state
}
}

export function searchCategories(state = [], action) {
switch (action.type) {
case 'SET_SEARCH_CATEGORIES':
return action.searchCategories

default:
return state
}
}

export function searchPage(state = 1, action) {
switch (action.type) {
case 'SET_SEARCH_PAGE':
return action.searchPage

default:
return state
}
}

/reducers/index.js:

import { combineReducers } from 'redux'
import { posts, totalPages, postsHasErrored, postsIsLoading } from './posts'
import { searchString, searchCategories, searchPage } from './searchQueries'

export default combineReducers({
posts,
postsHasErrored,
postsIsLoading,
totalPages,

searchString,
searchCategories,
searchPage
})

/components/PostsList.js

// dependencies
import React, { Component } from 'react'
import axios from 'axios'
import { connect } from 'react-redux'
// components
import PostsListItem from './PostsListItem'
import PostsPages from './PostsPages'
// actions
import { postsFetchData } from '../actions/posts'
import { searchQueriesSetting } from '../actions/searchQueries'
// styles
import '../styles/css/postsList.css'
// shared modules
import { createSearchUrl } from '../sharedModules/sharedModules'

class PostsList extends Component {

componentWillReceiveProps(nextProps) {
if (nextProps.searchPage !== this.props.searchPage) this.componentDidMount()
}

componentDidMount() {
this.props.searchQueriesSetting()
this.props.fetchData(createSearchUrl(
'http://localhost/wordpress-api/wp-json/wp/v2/posts?per_page=1',
this.props.searchCategories,
this.props.searchString,
this.props.searchPage
))
}


render() {
console.log(this.props)
const { isLoading, hasErrored, posts } = this.props
if (isLoading) return <div className='posts-list'><h2 className='loading'>Loading...</h2></div>

const postsList = posts.map(post => <PostsListItem post={post} key={post.id} />)

return (
<div className='posts-list'>
{postsList}
<PostsPages />
</div>
)
}
}

const mapStateToProps = (state) => {
return {
posts: state.posts,
hasErrored: state.postsHasErrored,
isLoading: state.postsIsLoading,
searchCategories: state.searchCategories,
searchString: state.searchString,
searchPage: state.searchPage
}
}
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(postsFetchData(url)),
searchQueriesSetting: () => dispatch(searchQueriesSetting())
}
}

export default connect(mapStateToProps, mapDispatchToProps)(PostsList)

/components/PostsPages.js

// dependencies
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
// actions
import { setSearchPage } from '../actions/searchQueries'
// shared modules
import { createSearchUrl } from '../sharedModules/sharedModules'

class PostsPages extends Component {
isLinkEdgy = (pageNumber) => {
if (parseInt(pageNumber, 10) <= 1) return ''
if (parseInt(pageNumber, 10) >= parseInt(this.props.totalPages, 10)) return this.props.totalPages
return pageNumber
}

render() {
const { totalPages, currentPage, searchCategories, searchString, setSearchPage } = this.props

const previousUrl = createSearchUrl('/blog', searchCategories, searchString, this.isLinkEdgy(parseInt(currentPage, 10) - 1))
const nextUrl = createSearchUrl('/blog', searchCategories, searchString, this.isLinkEdgy(parseInt(currentPage, 10) + 1))

return (
<div className='posts-pages'>
<ul className='posts-pages-list'>
<li><Link to={previousUrl} onClick={() => setSearchPage(this.isLinkEdgy(parseInt(currentPage, 10) - 1))}>Prev page</Link></li>
<li><Link to={nextUrl} onClick={() => setSearchPage(this.isLinkEdgy(parseInt(currentPage, 10) + 1))}>Next page</Link></li>
</ul>
</div>
)
}
}

const mapStateToProps = (state) => {
return {
totalPages: state.totalPages,
currentPage: state.searchPage,
searchCategories: state.searchCategories,
searchString: state.searchString
}
}
const mapDispatchToProps = (dispatch) => {
return {
setSearchPage: (searchPage) => dispatch(setSearchPage(searchPage))
}
}

export default connect(mapStateToProps, mapDispatchToProps)(PostsPages)

最佳答案

那是因为您访问了错误的状态部分。看一下您的 combineReducers 调用:

export default combineReducers({
posts,
postsHasErrored,
postsIsLoading,
totalPages,

setSearchString,
setSearchCategories,
setSearchPage
})

the Redux documentation :

combineReducers(reducers)

The shape of the state object matches the keys of the passed reducers.

因此,您的 state 对象实际上如下所示:

{
posts: ...,
postsHasErrored: ...,
postsIsLoading: ...,
totalPages: ...,
setSearchString: ...,
setSearchCategories: ...,
setSearchPage: ...
}

在您的 mapDispatchToProps 中,您尝试访问状态的错误部分:

currentPage: state.searchPage,
searchCategories: state.searchCategories,
searchString: state.searchString

由于 state.searchPage 和另外两个在 state 对象中不存在,你会得到 undefined。相反,请确保您访问与 reducer 同名的键:

currentPage: state.setSearchPage,
searchCategories: state.setSearchCategories,
searchString: state.setSearchString

或者只是重命名您的 reducer (这会更好,因为它们现在用词不当)。去掉 reducer 上的 set 前缀,它们不是操作

关于javascript - 为什么将状态映射到 props 会给出未定义的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45256875/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com