Javascript 获取error state.stories是不可编辑的
我正在创建一个react/redux应用程序,用户可以在其中登录并通过提交表单添加故事。故事作为一个对象提交,我想将这个故事添加到数组的对象中。但我不断收到一个错误,说Javascript 获取error state.stories是不可编辑的,javascript,arrays,reactjs,redux,state,Javascript,Arrays,Reactjs,Redux,State,我正在创建一个react/redux应用程序,用户可以在其中登录并通过提交表单添加故事。故事作为一个对象提交,我想将这个故事添加到数组的对象中。但我不断收到一个错误,说state.stories不可编辑,即使我在reducer中编写stories:[…state.stories,action.payload]。action.payload返回一个对象,我想将该对象放入数组中。 如何将action.payload对象插入数组?我希望故事是一组对象。 对于任何格式错误,我深表歉意 App.js im
state.stories不可编辑
,即使我在reducer中编写stories:[…state.stories,action.payload]
。action.payload返回一个对象,我想将该对象放入数组中。
如何将action.payload对象插入数组?我希望故事是一组对象。
对于任何格式错误,我深表歉意
App.js
import './App.scss';
import Login from './components/Login';
import { Router, Switch, Route, NavLink } from 'react-router-dom';
import PrivateRoute from './utils/PrivateRoute';
import CreateStory from './components/CreateStory';
import history from './utils/history';
function App() {
return (
<div className="App">
<Router history={history}>
<Switch>
<Route exact path="/" component={Login} />
<PrivateRoute path="/user" component={CreateStory}/>
</Switch>
</Router>
</div>
);
}
export default App;
initialState.js:
import { getToken } from '../utils/Common'
export const initialState = {
isLoggedIn: false,
userId: '',
role: 'user',
token: getToken,
data: '',
};
reducers.js
import { initialState } from './initialState';
import * as t from './actionTypes';
export const loginReducer = (state = initialState, action) => {
switch (action.type) {
case t.SET_ROLE_STATE:
return {
...state,
role: action.payload,
};
case t.SET_LOGIN_STATE:
return {
...state,
...action.payload, // this is what we expect to get back from API call and login page input
isLoggedIn: true, // we set this as true on login
};
default:
return state;
}
};
export const storyReducer = (state = initialState, action) => {
switch (action.type) {
case t.CREATE_STORY:
return {
...state,
story: [...state.stories, action.payload], //the error pops up at this line
};
default:
return state;
}
}
actions.js:
import * as t from './actionTypes';
import { setUserSession } from '../utils/Common';
// this is what our action should look like which dispatches the "payload" to reducer
const setLoginState = (loginData) => {
return {
type: t.SET_LOGIN_STATE,
payload: loginData, //{ ...json, userId: email }
};
};
const setStoryState = (storyData) => {
return {
type: t.CREATE_STORY,
payload: storyData,
};
};
export const login = (loginInput) => { //our login action
const { email, password } = loginInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/signin', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(loginInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
// console.log(json)
dispatch(setLoginState({ ...json, userId: email })); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
setUserSession(json.token, json.lastName)
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
};
export const roleChange = role => {
return {
type: t.SET_ROLE_STATE,
payload: role
};
}
export const createStory = storyInput => {
const { summary, description, type, complexity, time, cost } = storyInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/stories', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(storyInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
dispatch(setStoryState({ // our action is called here with object as parameter, this is our payload
summary: summary,
description: description,
type: type,
complexity: complexity,
time: time,
cost: cost
})); // our action is called here
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Some error occured, please retry');
console.log(err);
});
};
}
Common.js
// return the user data from the session storage
export const getUser = () => {
const userStr = sessionStorage.getItem('user');
if (userStr) return JSON.parse(userStr);
else return null;
}
// return the token from the session storage
export const getToken = () => {
return sessionStorage.getItem('token') || null;
}
// remove the token and user from the session storage
export const removeUserSession = () => {
sessionStorage.removeItem('token');
sessionStorage.removeItem('user');
}
// set the token and user from the session storage
export const setUserSession = (token, user) => {
sessionStorage.setItem('token', token);
sessionStorage.setItem('user', JSON.stringify(user));
}
更新:
我已更改为:
export const storyReducer = (state = {stories: []}, action) => {
switch (action.type) {
case t.CREATE_STORY:
return {
...state,
stories: [...state, action.payload],
};
// case t.ADD_STORY:
// return {
// ...state,
// stories: [...state.stories, action.payload], //stories is an object
// };
default:
return state;
}
}
现在,当添加第一个故事时,我没有得到错误。但是我在向数组中添加多个存储时出错。您对
loginReducer
和storyReducer
使用了相同的initialState
,而后者实际上无法使用,因为它没有stories
属性,因此您试图传播未定义的
使用两种不同的初始状态。它们也不必有这个名称,您可以随意命名;) 您的initialState
不包含stories
属性,因此initialState。stories
是未定义的
,而未定义的
是不可修改的。@secan我尝试过,但运气不好:(仍然会收到相同的错误消息您也有一个输入错误,请检查您所说的显示错误的行。您有story:[…state.stories,action.payload],
而不是stories:[…state.stories]
。请确保在初始状态下为stories
数组设置默认值,如前面提到的@secan。尝试检查state.stories
是否存在,然后添加else块进行调试。这将给出不可编辑的位置。我已将其更改为storyReducer=(state={stories:[],action)现在我可以将第一个故事添加到故事数组中,当我尝试添加另一个故事时,我得到了相同的错误。好了,现在我仍然无法添加任何内容,获得相同的数组,故事数组正在清空设置相同的*错误哦,还有,您的创建故事减速机应该有故事:[…state.stories,action.payload],
而不是故事:[…状态,动作.有效载荷],
另外,我建议你看看官方的redux教程和现代redux-你在这里写的是一种非常古老的redux风格,我们不再推荐了。所有这些事情可能都不会发生在现代redux上,所以看看;)
import { initialState } from './initialState';
import * as t from './actionTypes';
export const loginReducer = (state = initialState, action) => {
switch (action.type) {
case t.SET_ROLE_STATE:
return {
...state,
role: action.payload,
};
case t.SET_LOGIN_STATE:
return {
...state,
...action.payload, // this is what we expect to get back from API call and login page input
isLoggedIn: true, // we set this as true on login
};
default:
return state;
}
};
export const storyReducer = (state = initialState, action) => {
switch (action.type) {
case t.CREATE_STORY:
return {
...state,
story: [...state.stories, action.payload], //the error pops up at this line
};
default:
return state;
}
}
import * as t from './actionTypes';
import { setUserSession } from '../utils/Common';
// this is what our action should look like which dispatches the "payload" to reducer
const setLoginState = (loginData) => {
return {
type: t.SET_LOGIN_STATE,
payload: loginData, //{ ...json, userId: email }
};
};
const setStoryState = (storyData) => {
return {
type: t.CREATE_STORY,
payload: storyData,
};
};
export const login = (loginInput) => { //our login action
const { email, password } = loginInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/signin', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(loginInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
// console.log(json)
dispatch(setLoginState({ ...json, userId: email })); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
setUserSession(json.token, json.lastName)
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
};
export const roleChange = role => {
return {
type: t.SET_ROLE_STATE,
payload: role
};
}
export const createStory = storyInput => {
const { summary, description, type, complexity, time, cost } = storyInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/stories', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(storyInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
dispatch(setStoryState({ // our action is called here with object as parameter, this is our payload
summary: summary,
description: description,
type: type,
complexity: complexity,
time: time,
cost: cost
})); // our action is called here
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Some error occured, please retry');
console.log(err);
});
};
}
// return the user data from the session storage
export const getUser = () => {
const userStr = sessionStorage.getItem('user');
if (userStr) return JSON.parse(userStr);
else return null;
}
// return the token from the session storage
export const getToken = () => {
return sessionStorage.getItem('token') || null;
}
// remove the token and user from the session storage
export const removeUserSession = () => {
sessionStorage.removeItem('token');
sessionStorage.removeItem('user');
}
// set the token and user from the session storage
export const setUserSession = (token, user) => {
sessionStorage.setItem('token', token);
sessionStorage.setItem('user', JSON.stringify(user));
}
export const storyReducer = (state = {stories: []}, action) => {
switch (action.type) {
case t.CREATE_STORY:
return {
...state,
stories: [...state, action.payload],
};
// case t.ADD_STORY:
// return {
// ...state,
// stories: [...state.stories, action.payload], //stories is an object
// };
default:
return state;
}
}