Реагируйте, Redux не может прочитать свойство undefined - PullRequest
0 голосов
/ 20 июня 2020

Имея проблему с mapStateToProps в Redux, он думает, что переменная не определена. Код ниже. Я как бы новичок в Redux и JavaScript, так что это не имеет смысла, как это исправить. Для контекста я пытаюсь отобразить этот компонент Reddit как одну из страниц веб-сайта, но у меня возникла эта проблема, и я не знаю, что делать дальше.

Reddit. js

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { selectSubreddit, fetchPostsIfNeeded, invalidateSubreddit } from '../actions'
import Picker from './Picker'
import Posts from './Posts'

import {Button, ListGroup} from 'react-bootstrap';
class Reddit extends Component {
  static propTypes = {
    selectedSubreddit: PropTypes.string.isRequired,
    posts: PropTypes.array.isRequired,
    isFetching: PropTypes.bool.isRequired,
    lastUpdated: PropTypes.number,
    dispatch: PropTypes.func.isRequired
  }

  componentDidMount() {
    const { dispatch, selectedSubreddit } = this.props
    dispatch(fetchPostsIfNeeded(selectedSubreddit))
  }

  componentDidUpdate(prevProps) {
    if (prevProps.selectedSubreddit !== this.props.selectedSubreddit) {
      const { dispatch, selectedSubreddit } = this.props
      dispatch(fetchPostsIfNeeded(selectedSubreddit))
    }
  }

  handleChange = nextSubreddit => {
    this.props.dispatch(selectSubreddit(nextSubreddit))
  }

  handleRefreshClick = e => {
    e.preventDefault()

    const { dispatch, selectedSubreddit } = this.props
    dispatch(invalidateSubreddit(selectedSubreddit))
    dispatch(fetchPostsIfNeeded(selectedSubreddit))
  }

  render() {
    const { selectedSubreddit, posts, isFetching, lastUpdated } = this.props
    const isEmpty = posts.length === 0
    return (
      <ListGroup>
        <Picker value={selectedSubreddit}
                onChange={this.handleChange}
                options={[ 'pokemon', 'csMajors' ]} />
        <p>
          {lastUpdated &&
            <span>
              Last updated at {new Date(lastUpdated).toLocaleTimeString()}.
              {' '}
            </span>
          }
          {!isFetching &&
            <Button onClick={this.handleRefreshClick}>
              Refresh
            </Button>
          }
        </p>
        {isEmpty
          ? (isFetching ? <h2>Loading...</h2> : <h2>Empty.</h2>)
          : <div style={{ opacity: isFetching ? 0.5 : 1 }}>
              <Posts posts={posts} />
            </div>
        }
      </ListGroup>

    )
  }
}

const mapStateToProps = state => {
  const { selectedSubreddit, postsBySubreddit } = state
  const {
    isFetching,
    lastUpdated,
    items: posts
  } = postsBySubreddit[selectedSubreddit] || {
    isFetching: true,
    items: []
  }

  return {
    selectedSubreddit,
    posts,
    isFetching,
    lastUpdated
  }
}

export default connect(mapStateToProps)(Reddit)

Picker. js component

import React from 'react'
import PropTypes from 'prop-types'

const Picker = ({ value, onChange, options }) => (
  <span>
    <h1>{value}</h1>
    <select onChange={e => onChange(e.target.value)}
            value={value}>
      {options.map(option =>
        <option value={option} key={option}>
          {option}
        </option>)
      }
    </select>
  </span>
)

Picker.propTypes = {
  options: PropTypes.arrayOf(
    PropTypes.string.isRequired
  ).isRequired,
  value: PropTypes.string.isRequired,
  onChange: PropTypes.func.isRequired
}

export default Picker

Post. js component

import React from 'react'
import PropTypes from 'prop-types'
import {ListGroup, Link} from 'react-bootstrap';
const Posts = ({posts}) => (
  <ListGroup>
    {posts.map((post, i) =>
      <ListGroup.Item Link key={i}>{post.title} <a href={post.url} >Post Link</a> </ListGroup.Item>
    )}
  </ListGroup>
)

Posts.propTypes = {
  posts: PropTypes.array.isRequired
}

export default Posts


index. js reducer

import { combineReducers } from 'redux'
import {
  SELECT_SUBREDDIT, INVALIDATE_SUBREDDIT,
  REQUEST_POSTS, RECEIVE_POSTS
} from '../actions'

const selectedSubreddit = (state = 'reactjs', action) => {
  switch (action.type) {
    case SELECT_SUBREDDIT:
      return action.subreddit
    default:
      return state
  }
}

const posts = (state = {
  isFetching: false,
  didInvalidate: false,
  items: []
}, action) => {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
      return {
        ...state,
        didInvalidate: true
      }
    case REQUEST_POSTS:
      return {
        ...state,
        isFetching: true,
        didInvalidate: false
      }
    case RECEIVE_POSTS:
      return {
        ...state,
        isFetching: false,
        didInvalidate: false,
        items: action.posts,
        lastUpdated: action.receivedAt
      }
    default:
      return state
  }
}

const postsBySubreddit = (state = { }, action) => {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
    case RECEIVE_POSTS:
    case REQUEST_POSTS:
      return {
        ...state,
        [action.subreddit]: posts(state[action.subreddit], action)
      }
    default:
      return state
  }
}

const rootReducer = combineReducers({
  postsBySubreddit,
  selectedSubreddit
})

export default rootReducer

index. js действия

export const REQUEST_POSTS = 'REQUEST_POSTS'
export const RECEIVE_POSTS = 'RECEIVE_POSTS'
export const SELECT_SUBREDDIT = 'SELECT_SUBREDDIT'
export const INVALIDATE_SUBREDDIT = 'INVALIDATE_SUBREDDIT'

export const selectSubreddit = subreddit => ({
  type: SELECT_SUBREDDIT,
  subreddit
})

export const invalidateSubreddit = subreddit => ({
  type: INVALIDATE_SUBREDDIT,
  subreddit
})

export const requestPosts = subreddit => ({
  type: REQUEST_POSTS,
  subreddit
})

export const receivePosts = (subreddit, json) => ({
  type: RECEIVE_POSTS,
  subreddit,
  posts: json.data.children.map(child => child.data),
  receivedAt: Date.now()
})

const fetchPosts = subreddit => dispatch => {
  dispatch(requestPosts(subreddit))
  return fetch(`https://www.reddit.com/r/${subreddit}.json`)
    .then(response => response.json())
    .then(json => dispatch(receivePosts(subreddit, json)))
}

const shouldFetchPosts = (state, subreddit) => {
  const posts = state.postsBySubreddit[subreddit]
  if (!posts) {
    return true
  }
  if (posts.isFetching) {
    return false
  }
  return posts.didInvalidate
}

export const fetchPostsIfNeeded = subreddit => (dispatch, getState) => {
  if (shouldFetchPosts(getState(), subreddit)) {
    return dispatch(fetchPosts(subreddit))
  }
}

Имея проблему с mapStateToProps в Redux, он думает, что переменная не определена. Код ниже.

Я немного новичок в Redux и JavaScript, так что это не имеет смысла, как это исправить. Для контекста я пытаюсь отобразить этот компонент Reddit как одну из страниц веб-сайта, но у меня возникла эта проблема, и я не знаю, что делать дальше.

Имея проблему с mapStateToProps в Redux, он считает, что переменная не определена. Код ниже. Я как бы новичок в Redux и JavaScript, поэтому на самом деле не имеет смысла, как это исправить.

Для контекста я пытаюсь отобразить этот компонент Reddit как одну из страниц веб-сайта, но У меня была эта проблема, и я не знаю, что делать дальше. Имея проблему с mapStateToProps в Redux, он считает, что переменная не определена.

Код ниже. Я как бы новичок в Redux и JavaScript, так что это не совсем понятно, как это исправить.

Для контекста я пытаюсь отобразить этот компонент Reddit как одну из страниц веб-сайта, но У меня возникла эта проблема, и я не знаю, что делать дальше.

Имея проблему с mapStateToProps в Redux, он считает, что переменная не определена. Код ниже.

Я новичок в Redux и JavaScript, так что это не совсем понятно, как это исправить.

Для контекста я пытаюсь визуализировать этот Reddit компонент в качестве одной из страниц веб-сайта, но у меня возникла эта проблема, и я не знаю, как действовать.

1 Ответ

0 голосов
/ 21 июня 2020

На самом деле вы не говорите, какая переменная в undefined, что является важной деталью вопроса. Тем не менее, я рискую и предполагаю, что это posts, потому что он впервые появляется в операторе возврата mapStateToProps:

return {
    selectedSubreddit,
    posts, <----- never defined
    isFetching,
    lastUpdated
  }

Возможно, вы имели в виду items? Вы go пытаетесь вытащить его из своего selectedSubreddit объекта, но не включаете его в возврат.

...