问题
I've been debugging why my state hasn't been changing and noticed this being logged in my reducer:
{ type: '@@redux/INITi.8.g.w.a.m' }
This is the store which includes state, action types, reducer, actions:
/* initial state */
import axios from 'axios';
export var usersStartState = {
accountNotVerified: null,
isLoggedIn: false,
error: true,
userAvatar: 'uploads/avatar/placeholder.jpg'
};
/* action types */
export const actionTypes = {
RESET_USER_ACCOUNT_IS_VERIFIED: 'RESET_USER_ACCOUNT_IS_VERIFIED',
USER_ACCOUNT_IS_VERIFIED: 'USER_ACCOUNT_IS_VERIFIED',
USER_ACCOUNT_NOT_VERIFIED: 'USER_ACCOUNT_NOT_VERIFIED',
IS_LOGGED_IN: 'IS_LOGGED_IN',
IS_LOGGED_OUT: 'IS_LOGGED_OUT',
LOAD_USER_AVATAR: 'LOAD_USER_AVATAR',
ERROR_LOADING: 'ERROR_LOADING' // LOAD_MULTER_IMAGE: "LOAD_MULTER_IMAGE"
};
/* reducer(s) */
export default function users(state = usersStartState, action) {
console.log('In users reducer! ', action);
switch (action.type) {
case actionTypes.RESET_USER_ACCOUNT_IS_VERIFIED:
return Object.assign({}, state, { accountNotVerified: null });
case actionTypes.USER_ACCOUNT_IS_VERIFIED:
return Object.assign({}, state, { accountNotVerified: false });
case actionTypes.USER_ACCOUNT_NOT_VERIFIED:
return Object.assign({}, state, { accountNotVerified: true });
case actionTypes.IS_LOGGED_IN:
return Object.assign({}, state, { isLoggedIn: true });
case actionTypes.IS_LOGGED_OUT:
return Object.assign({}, state, { isLoggedIn: false });
case actionTypes.LOAD_USER_AVATAR:
return { ...state, userAvatar: action.data };
case actionTypes.ERROR_LOADING:
return Object.assign({}, state, { error: true });
default:
return state;
}
}
/* actions */
export const resetUserAcoountVerified = () => {
return { type: actionTypes.RESET_USER_ACCOUNT_IS_VERIFIED };
};
export const userHasBeenVerified = () => {
return { type: actionTypes.USER_ACCOUNT_IS_VERIFIED };
};
export const userHasNotBeenVerified = () => {
return { type: actionTypes.USER_ACCOUNT_NOT_VERIFIED };
};
export const logInUser = () => {
return { type: actionTypes.IS_LOGGED_IN };
};
export const logOutUser = () => {
axios
.get('/users/logout')
.then(response => {
if (response.status === 200) {
console.log('You have been logged out!');
}
})
.catch(function(error) {
if (error.response.status === 500) {
console.log('An error has occured');
}
});
return { type: actionTypes.IS_LOGGED_OUT };
};
export const loadAvatar = data => {
console.log('in load avatar ', data);
return { type: actionTypes.LOAD_USER_AVATAR, data: data };
};
export const errorLoading = () => {
return { type: actionTypes.ERROR_LOADING };
};
And this is my component:
import { useState } from 'react';
import { Card, Icon, Image, Segment, Form } from 'semantic-ui-react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { loadAvatar } from '../../store/reducers/users/index';
import axios from 'axios';
function ImageUploader({ userAvatar }) {
var [localUserAvatar, setLocalUserAvatar] = useState(userAvatar);
function fileUploader(e) {
e.persist();
var imageFormObj = new FormData();
imageFormObj.append('imageName', 'multer-image-' + Date.now());
imageFormObj.append('imageData', e.target.files[0]);
loadAvatar('foo');
axios({
method: 'post',
url: `/users/uploadmulter`,
data: imageFormObj,
config: { headers: { 'Content-Type': 'multipart/form-data' } }
})
.then(data => {
if (data.status === 200) {
console.log('data ', data);
console.log('path typeof ', typeof data.data.path);
loadAvatar('foo');
setLocalUserAvatar('../../' + data.data.path);
}
})
.catch(err => {
alert('Error while uploading image using multer');
});
}
Here are console.log('userAvatar in imageUploader ', userAvatar); console.log('Date.now() line 44 in imageUploader ', Date.now()); console.log('localUserAvatar in imageUploader ', localUserAvatar); console.log('Date.now() line 46 in imageUploader ', Date.now());
console.log("loadAvatar('barbar') ", loadAvatar('barbar'));
return (
<>
<Segment>
<Card fluid>
<Image src={localUserAvatar} alt="upload-image" />
<Segment>
<Form encType="multipart/form-data">
<Form.Field>
<input
placeholder="Name of image"
className="process__upload-btn"
type="file"
content="Edit your Avatar!"
onChange={e => fileUploader(e)}
/>
</Form.Field>
</Form>
</Segment>
<Card.Content>
<Card.Header>Charly</Card.Header>
<Card.Meta>
<span className="date">Joined in 2015</span>
</Card.Meta>
<Card.Description>Charly</Card.Description>
</Card.Content>
<Card.Content extra>
<a>
<Icon name="user" />
22 Friends
</a>
</Card.Content>
</Card>
</Segment>
</>
);
}
function mapStateToProps(state) {
const { users } = state;
const { userAvatar } = users;
return { userAvatar };
}
const mapDispatchToProps = dispatch => bindActionCreators({ loadAvatar }, dispatch);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ImageUploader);
From the logs you can see loadAvatar
the dispatcher, gets fired in the component and in the store...
But the state in the store never changes....
Also other states do change correctly...Like for example I have a Modal and that updates nicely.
Any help would be appreciated as what { type: '@@redux/INITi.8.g.w.a.m' }
and why my state is not updating?
回答1:
Redux dispatches that action as an internal initialization step:
// When a store is created, an "INIT" action is dispatched so that every
// reducer returns their initial state. This effectively populates
// the initial state tree.
dispatch({ type: ActionTypes.INIT })
It's specifically so that your reducers will see the action, not recognize the action type, and return their default state, thus defining the initial overall app state contents.
来源:https://stackoverflow.com/questions/61987537/redux-my-state-is-receiving-redux-initi-8-g-w-a-m-redux-state-not-updating