(Продолжение до: Как использовать redux-thunk со стороны сервера узла? )
Требования: минимальный рабочий пример redux-thunk.
В этом вопросе я попробовал комбинацию нод + нодмон + редукс + редукс_тунк + бабел. (в предыдущем вопросе я не использовал nodemon и babel).
Ошибка (в основном такая же, как в предыдущем вопросе)
(node:34825) ExperimentalWarning: The ESM module loader is experimental.
applyMiddleware [Function: applyMiddleware]
/home/code/redux/tutorial_async_actions/node_modules/redux/lib/redux.js:648
return middleware(middlewareAPI);
^
TypeError: middleware is not a function
at /home/code/redux/tutorial_async_actions/node_modules/redux/lib/redux.js:648:16
at Array.map (<anonymous>)
at /home/code/redux/tutorial_async_actions/node_modules/redux/lib/redux.js:647:31
at createStore (/home/code/redux/tutorial_async_actions/node_modules/redux/lib/redux.js:85:33)
at file:///home/a/code/redux/tutorial_async_actions/index.js:15:15
at ModuleJob.run (internal/modules/esm/module_job.js:110:37)
at async Loader.import (internal/modules/esm/loader.js:164:24)
[nodemon] app crashed - waiting for file changes before starting...
Здесь мои попытки
Основное * Файл 1028 * (обратите внимание на две разные попытки импорта ... обе неудачные)
//import { createStore, applyMiddleware } from 'redux';
import redux from 'redux';
const { createStore, applyMiddleware } = redux;
// import { thunkMiddleware } from 'redux-thunk'
import reduxThunk from 'redux-thunk'
const { thunkMiddleware } = reduxThunk;
import { selectSubreddit, fetchPosts } from './actions.js'
import rootReducer from './reducers.js'
console.log('applyMiddleware', applyMiddleware);
const store = createStore(
rootReducer,
applyMiddleware(thunkMiddleware)
);
store.dispatch(selectSubreddit('reactjs'));
store.dispatch(fetchPosts('reactjs')).then(() => console.log(store.getState()));
пакет. json
{
"name": "redux_async_actions",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon --exec babel-node ./index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/node": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@babel/preset-react": "^7.8.3",
"nodemon": "^2.0.2"
}
}
А вот babel.r c
{
"presets": [
"@babel/preset-env",
"react-app"
]
}
действия. js
export const SELECT_SUBREDDIT = 'SELECT_SUBREDDIT'
export function selectSubreddit(subreddit) {
return {
type: SELECT_SUBREDDIT,
subreddit
};
}
export const INVALIDATE_SUBREDDIT = 'INVALIDATE_SUBREDDIT'
function invalidateSubreddit(subreddit) {
return {
type: INVALIDATE_SUBREDDIT,
subreddit
};
}
export const REQUEST_POSTS = 'REQUEST_POSTS'
function requestPosts(subreddit) {
return {
type: REQUEST_POSTS,
subreddit
}
}
export const RECEIVE_POSTS = 'RECEIVE_POSTS'
function receivePosts(subreddit, json) {
return {
type: RECEIVE_POSTS,
subreddit,
posts: json.data.children.map(child => child.data),
receivedAt: Date.now()
}
}
export function fetchPosts(subreddit) {
return function (dispatch) {
dispatch(requestPosts(subreddit));
return fetch(`https://www.reddit.com/r/${subreddit}.json`)
.then(
response => response.json(),
error => console.log('An error occurred.', error)
)
.then(json =>
dispatch(receivePosts(subreddit, json))
)
}
}
редукторы. js
import redux from 'redux';
const { combineReducers } = redux;
import {
SELECT_SUBREDDIT,
INVALIDATE_SUBREDDIT,
REQUEST_POSTS,
RECEIVE_POSTS
} from './actions.js';
function selectedSubreddit(state = 'reactjs', action) {
switch (action.type) {
case SELECT_SUBREDDIT:
return action.subreddit
default:
return state
}
}
function posts(
state = {
isFetching: false,
didInvalidate: false,
items: []
},
action
) {
switch (action.type) {
case INVALIDATE_SUBREDDIT:
return Object.assign({}, state, { didInvalidate: true })
case REQUEST_POSTS:
return Object.assign({}, state, { isFetching: true, didInvalidate: false });
case RECEIVE_POSTS:
return Object.assign({}, state, {
isFetching: false, didInvalidate: false,
items: action.posts,
lastUpdated: action.receivedAt
});
default:
return state;
}
}
function postsBySubreddit(state = {}, action) {
switch (action.type) {
case INVALIDATE_SUBREDDIT:
case RECEIVE_POSTS:
case REQUEST_POSTS:
return Object.assign({}, state, {
[action.subreddit]: posts(state[action.subreddit], action)
});
default:
return state
}
}
const rootReducer = combineReducers({
postsBySubreddit,
selectedSubreddit
});
export default rootReducer;