Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么将状态映射到道具会给出未定义的属性?_Javascript_Reactjs_Ecmascript 6_Redux - Fatal编程技术网

Javascript 为什么将状态映射到道具会给出未定义的属性?

Javascript 为什么将状态映射到道具会给出未定义的属性?,javascript,reactjs,ecmascript-6,redux,Javascript,Reactjs,Ecmascript 6,Redux,我的Redux设置有问题。我对单个文件的postsactions和reducer没有问题,但只要添加searchquerys部分,它就只显示searchquerys道具的未定义的值 我已经尝试过尽可能地复制它,并为第二组操作/简化程序修改它,但在搜索查询的情况下,我仍然会使用未定义的道具。我得到了所有的道具,包括帖子的默认值。以下是每一项的代码: /actions/posts.js: import axios from 'axios' export function postsHasError

我的Redux设置有问题。我对单个文件的
posts
actions和reducer没有问题,但只要添加
searchquerys
部分,它就只显示
searchquerys
道具的
未定义的值

我已经尝试过尽可能地复制它,并为第二组操作/简化程序修改它,但在
搜索查询
的情况下,我仍然会使用
未定义的
道具。我得到了所有的道具,包括
帖子的默认值。以下是每一项的代码:

/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)))
  }
}
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
  }
}
/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')))
  }
}
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/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')))
  }
}
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
})
/组件/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)
//依赖项
从“React”导入React,{Component}
从“axios”导入axios
从“react redux”导入{connect}
//组成部分
从“./postslitem”导入postslitem
从“./PostsPages”导入PostsPages
//行动
从“../actions/posts”导入{postsFetchData}
从“../actions/searchQueries”导入{searchQueriesSetting}
//风格
导入“../styles/css/postsList.css”
//共享模块
从“../sharedModules/sharedModules”导入{createSearchUrl}
类PostsList扩展了组件{
组件将接收道具(下一步){
如果(nextrops.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',
这个.props.searchCategories,
this.props.searchString,
此.props.searchPage
))
}
render(){
console.log(this.props)
const{isLoading,haserroed,posts}=this.props
如果(正在加载)返回加载。。。
const postsList=posts.map(post=>)
返回(
{postsList}
)
}
}
常量mapStateToProps=(状态)=>{
返回{
职位:state.posts,
hasserrored:state.postsHasErrored,
isLoading:state.postsIsLoading,
searchCategories:state.searchCategories,
searchString:state.searchString,
searchPage:state.searchPage
}
}
const mapDispatchToProps=(调度)=>{
返回{
fetchData:(url)=>dispatch(postsFetchData(url)),
searchQueriesSetting:()=>dispatch(searchQueriesSetting())
}
}
导出默认连接(mapStateToProps、mapDispatchToProps)(PostsList)
/组件/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)
//依赖项
从“React”导入React,{Component}
从“react router dom”导入{Link}
从“react redux”导入{connect}
//行动
从“../actions/searchQueries”导入{setSearchPage}
//共享模块
从“../sharedModules/sharedModules”导入{createSearchUrl}
类PostsPages扩展组件{
isLinkEdgy=(页码)=>{
如果(parseInt(pageNumber,10)=parseInt(this.props.totalPages,10))返回this.props.totalPages
返回页码
}
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))
返回(
  • setSearchPage(this.isLinkEdgy(parseInt(currentPage,10)-1))}>Prev page
  • setSearchPage(this.isLinkEdgy(parseInt(currentPage,10)+1))}>下一页
) } } 常量mapStateToProps=(状态)=>{ 返回{ totalPages:state.totalPages, currentPage:state.searchPage, searchCategories:state.searchCategories, searchString:state.searchString } } const mapDispatchToProps=(调度)=>{ 返回{ setSearchPage:(searchPage)=>调度(setSearchPage(searchPage)) } } 导出默认连接(mapStateToProps、mapDispatchToProps)(PostsPages)
<>代码>这是因为你正在访问错误的状态。查看您的
组合减速机
呼叫:

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

  setSearchString,
  setSearchCategories,
  setSearchPage
})
Per:

组合减速器(减速器)
状态对象的形状与传递的
减缩器的键匹配

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

{
  posts: ...,
  postsHasErrored: ...,
  postsIsLoading: ...,
  totalPages: ...,
  setSearchString: ...,
  setSearchCategories: ...,
  setSearchPage: ...
}
在您的
mapDispatchToProps
中,您试图访问错误的状态部分:

currentPage: state.searchPage,
searchCategories: state.searchCategories,
searchString: state.searchString
由于
state.searchPage
和另外两个不存在于
state
对象中,因此您会得到
未定义的
。相反,请确保访问与减速器同名的键:

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

或者只是重新命名你的减速机(这将是更好的,因为他们是误称现在)。在减法器中去掉<代码>设置<代码>前缀,它们不是动作。

这是因为您访问了状态的错误PAR。查看您的
组合减速机
呼叫:

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

  setSearchString,
  setSearchCategories,
  setSearchPage
})
Per:

组合减速器(减速器)
状态对象的形状与传递的
减缩器的键匹配

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

{
  posts: ...,
  postsHasErrored: ...,
  postsIsLoading: ...,
  totalPages: ...,
  setSearchString: ...,
  setSearchCategories: ...,
  setSearchPage: ...
}
在您的
mapDispatchToProps
中,您试图访问错误的状态部分:

currentPage: state.searchPage,
searchCategories: state.searchCategories,
searchString: state.searchString
由于
state.searchPage
和另外两个不存在于
state
对象中,因此您会得到
未定义的
。相反,请确保访问与减速器同名的键:

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

或者只是重新命名你的减速机(这将是更好的,因为他们是误称现在)。去掉减速机上的
set
前缀,它们不是动作。

非常感谢。这太简单了。只是点名而已。你知道有什么开发工具可以发现命名不匹配吗?也许还有一些阅读材料,以防你认为我可以改进代码中的一两件事?@MateuszMysiak