長文すみません。
react-redux-routerを勉強しているのですが、どのサンプルを入力しても同様のエラーが出て何か基本的な所で躓いているようなのですが解決できずに困っています。
ご指導いただけないでしょうか?
- WSL ubuntu 18.04
- yarn 1.13.0
- npm 6.4.1
yarn add redux react-redux redux-thunk redux-logger react-router-dom react-router-redux@next history --dev
↓ インストール直後のpackage.jsonです
JavaScript
1{ 2 "name": "my-project", 3 "version": "0.1.0", 4 "private": true, 5 "dependencies": { 6 "react": "^16.7.0", 7 "react-dom": "^16.7.0", 8 "react-scripts": "2.1.3" 9 }, 10 "scripts": { 11 "start": "react-scripts start", 12 "build": "react-scripts build", 13 "test": "react-scripts test", 14 "eject": "react-scripts eject" 15 }, 16 "eslintConfig": { 17 "extends": "react-app" 18 }, 19 "browserslist": [ 20 ">0.2%", 21 "not dead", 22 "not ie <= 11", 23 "not op_mini all" 24 ], 25 "devDependencies": { 26 "history": "^4.7.2", 27 "react-redux": "^6.0.0", 28 "react-router-dom": "^4.3.1", 29 "react-router-redux": "^5.0.0-alpha.9", 30 "redux": "^4.0.1", 31 "redux-logger": "^3.0.6", 32 "redux-thunk": "^2.3.0" 33 } 34}
この後、fetch-jsonpとqsをインストールしています。
翔泳社のReact入門のサンプルを入力するとエラーとなって実行できません。
以下import等端折ったソースです。
__↓ src/index.js __
JavaScript
1const history = createBrowserHistory(); 2const store = createStore(history); 3 4ReactDOM.render( 5 <Provider store={store}> 6 <ConnectedRouter history={history}> 7 <App /> 8 </ConnectedRouter> 9 </Provider>, 10 document.getElementById('root') 11); 12
__↓ src/components/Nav.js 及び src/components/Ranking.js __
JavaScript
1//Nav.js 2export default function Nav({ categories }) { 3 const to = category => ( 4 category.id === '1' ? '/all' : `/category/${category.id}` 5 ); 6 7 return ( 8 <ul> 9 {categories.map(category => ( 10 <li key={`nav-item-${category.id}`}> 11 <Link to={to(category)}> 12 {category.name} 13 </Link> 14 </li> 15 ))} 16 </ul> 17 ); 18} 19Nav.propTypes = { 20 categories: PropTypes.arrayOf( 21 PropTypes.shape({ 22 id: PropTypes.string.isRequired, 23 name: PropTypes.string.isRequired 24 }) 25 ).isRequired 26}; 27 28 29//Ranking.js 30export default class Ranking extends React.Component { 31 componentWillMount() { 32 this.props.onMount(this.props.categoryId); 33 } 34 componentWillReceiveProps(nextProps) { 35 if (this.props.categoryId !== nextProps.categoryId) { 36 this.props.onUpdate(nextProps.categoryId); 37 } 38 } 39 40 render() { 41 const { category, ranking, error } = this.props; 42 43 return ( 44 <div> 45 <h2>{ 46 typeof category !== 'undefined' ? `${category.name}のランキング` : '' 47 }</h2> 48 49 {(() => { 50 if (error) { 51 return <p>エラーが発生しました。リロードしてください。</p>; 52 } else if (typeof ranking === 'undefined') { 53 return <p>読み込み中...</p>; 54 } else { 55 return ( 56 <ol> 57 {ranking.map(item => ( 58 <li key={`ranking-item-${item.code}`}> 59 <img alt={item.name} src={item.imageUrl} /> 60 <a href={item.url} target="_blank">{item.name}</a> 61 </li> 62 ))} 63 </ol> 64 ); 65 } 66 })()} 67 </div> 68 ); 69 } 70} 71Ranking.propTypes = { 72 categoryId: PropTypes.string.isRequired, 73 onMount: PropTypes.func.isRequired, 74 onUpdate: PropTypes.func.isRequired, 75 76 category: PropTypes.shape({ 77 id: PropTypes.string.isRequired, 78 name: PropTypes.string.isRequired, 79 }), 80 ranking: PropTypes.arrayOf( 81 PropTypes.shape({ 82 code: PropTypes.string.isRequired, 83 name: PropTypes.string.isRequired, 84 url: PropTypes.string.isRequired, 85 imageUrl: PropTypes.string.isRequired, 86 }) 87 ), 88 error: PropTypes.bool.isRequired 89}; 90Ranking.defaultProps = { 91 categoryId: '1' 92}; 93
__↓ src/containers/Nav.js 及び src/containers/Ranking.js __
JavaScript
1//Nav.js 2const mapStateToProps = state => ({ 3 categories: state.shopping.categories 4}); 5export default connect(mapStateToProps)(Nav); 6 7 8//Ranking.js 9const mapStateToProps = (state, ownProps) => ({ 10 categoryId: ownProps.categoryId, 11 12 category: state.Ranking.category, 13 ranking: state.Ranking.ranking, 14 error: state.Ranking.error 15}); 16 17const mapDispatchToProps = dispatch => ({ 18 onMount (categoryId) { 19 dispatch(actions.fetchRanking(categoryId)); 20 }, 21 onUpdate (categoryId) { 22 dispatch(actions.fetchRanking(categoryId)); 23 } 24}); 25export default connect(mapStateToProps, mapDispatchToProps)(Ranking);
__↓ src/reducers/index.js、src/reducers/Ranking.js 及び src/reducers/shopping.js __
JavaScript
1//index.js 2export { default as shopping } from './shopping'; 3export { default as Ranking } from './Ranking'; 4 5//Ranking.js 6const getRanking = response => { 7 const ranking = []; 8 const itemLength = response.ResultSet.totalResultsReturned 9 for (let index = 0; index < itemLength; index++) { 10 const item = response.ResultSet['0'].Result[index + '']; 11 ranking.push({ 12 code: item.Code, 13 name: item.Name, 14 url: item.Url, 15 imageUrl: item.Image.Medium 16 }) 17 } 18 return ranking; 19}; 20 21const initialState = { 22 category: undefined, 23 ranking: undefined, 24 error: false 25}; 26 27export default (state = initialState, action) => { 28 switch (action.type) { 29 case 'START_REQUEST': 30 return { 31 category: action.payload.category, 32 ranking: undefined, 33 error: false 34 }; 35 36 case 'RECEIVE_DATA': 37 return action.payload.error 38 ? { ...state, error: true } 39 : { ...state, ranking: getRanking(action.payload.response) }; 40 41 default: 42 return state; 43 } 44} 45 46//shopping.js 47const initialState = { 48 categories: [ 49 { id: '1', name: 'すべてのカテゴリ' }, 50 { id: '2502', name: 'パソコン、周辺機器' }, 51 { id: '10002', name: '本、雑誌、コミック' } 52 ] 53}; 54export default () => initialState;
__↓ src/actions/Ranking.js __
JavaScript
1const API_URL = 'yahooのAPIリクエストURL'; 2const APP_ID = '自分がyahooで取得したID'; 3 4const startRequest = category => ({ 5 type: 'START_REQUEST', 6 payload: { category }, 7}); 8const receiveData = (category, error, response) => ({ 9 type: 'RECEIVE_DATA', 10 payload: { category, error, response }, 11}); 12const finishRequest = category => ({ 13 type: 'FINISH_REQUEST', 14 payload: { category }, 15}); 16 17// ランキングを取得する 18export const fetchRanking = categoryId => { 19 return async (dispatch, getState) => { 20 const categories = getState().shopping.categories; 21 const category = categories.find(category => (category.id === categoryId)); 22 if (typeof category === 'undefined') { 23 dispatch(replace('/')); 24 return; 25 } 26 dispatch(startRequest(category)); 27 28 const queryString = qs.stringify({ 29 appid: APP_ID, 30 category_id: categoryId, 31 }); 32 try { 33 const responce = await fetchJsonp(`${API_URL}?${queryString}`); 34 const data = await responce.json(); 35 dispatch(receiveData(category, null, data)); 36 } catch (err) { 37 dispatch(receiveData(category, err)); 38 } 39 dispatch(finishRequest(category)); 40 }; 41}; 42
__ ↓ src/createStore.js __
JavaScript
1export default function createStore(history) { 2 return reduxCreateStore( 3 combineReducers({ 4 ...reducers, 5 router: routerReducer, 6 }), 7 applyMiddleware( 8 logger, 9 thunk, 10 routerMiddleware(history) 11 ) 12 ); 13}
__ ↓ src/fetchRanking.js __
JavaScript
1const API_URL = 'yahooのAPIリクエストURL'; 2const APP_ID = '自分がyahooで取得したID'; 3 4export default function fetchRanking(categoryId) { 5 const queryString = qs({ 6 appid: APP_ID, 7 category_id: categoryId 8 }); 9 return fetchJsonp(`${API_URL}?${qs}`); 10}
__ ↓ src/App.js __
JavaScript
1class App extends Component { 2 render() { 3 return ( 4 <div className="App"> 5 <Nav /> 6 <Switch> 7 <Route path="/all" component={Ranking} /> 8 <Route 9 path="/category/1" 10 render={() => <Redirect to="/all" />} 11 /> 12 <Route 13 path="/category/:id" 14 render={ 15 ({ match }) => <Ranking categoryId={match.params.id} /> 16 } 17 /> 18 </Switch> 19 </div> 20 ); 21 } 22} 23export default App;
__ ↓ src/index.js[エントリーポイント] __
JavaScript
1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import { Provider } from 'react-redux'; 4import { ConnectedRouter } from 'react-router-redux'; 5import createBrowserHistory from 'history/createBrowserHistory'; 6import App from './App'; 7import createStore from './createStore'; 8 9const history = createBrowserHistory(); 10const store = createStore(history); 11 12ReactDOM.render( 13 <Provider store={store}> 14 <ConnectedRouter history={history}> 15 <App /> 16 </ConnectedRouter> 17 </Provider>, 18 document.getElementById('root') 19);
実行結果は
** TypeError: Cannot read property 'dispatch' of undefined **
となります。
プラウザコンソールのデバッガで追いかけたりしたのですが自己解決できそうにありません。
よろしくお願いします・
このサイトのサンプルでも同様のエラーが出ます。
回答1件
あなたの回答
tips
プレビュー