when i using redux in my react app,reducer just return initial state for me.which is always returned the false here.thanks for your answer.
[UPDATE]:
i chaned
let newState = state
to this:
let newState = {...state}
but also reducer returned false
this my reducer:
const initialState = {
modalVisible: false
};
function modalReducer(state = initialState, action) {
let newState = {...state};
switch (action.type) {
case "SHOW":
newState.modalVisible = true;
console.log("Show!");
break;
case "HIDE":
newState.modalVisible = false;
console.log("Hide!");
break;
}
return newState;
}
export default modalReducer;
and this is my component (Svg Viewer component)
import React from "react";
import { connect } from "react-redux";
const SvgViewer = ({
nodesData,
svgFilePath,
modalVisible,
onModalShow,
onModalHide
}) => {
const clickHandler = () => {
onModalShow();
console.log(modalVisible); //return false
onModalHide();
console.log(modalVisible);
};
return (
<div className="unit-schema-container1" key={svgFilePath}>
<object id="svgobject" type="image/svg+xml" data={svgFilePath}></object>
<button onClick={clickHandler}></button>
</div>
);
};
const mapStateToProps = state => {
return { modalVisible: state.modalVisible };
};
const mapDispatchToProps = dispatch => {
return {
onModalShow: () => {
dispatch({ type: "SHOW" });
},
onModalHide: () => {
dispatch({ type: "HIDE" });
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(SvgViewer);
You should try using this. Its easier to read and uses the best practices
const initialState = {
modalVisible: false
};
function modalReducer(state = initialState, action) {
switch (action.type) {
case "SHOW":
return {...state, modalVisible: true }
case "HIDE":
return {...state, modalVisible: false }
default:
return state
}
}
you should return a new state object
let newState = {...state}
I think the problem is in mapStateToprops function, please post your main reducer,
try to edit you mapStateToProps
const mapStateToProps = state => {
return { modalVisible: state.modalVisible.modalVisible };
};
Related
i've been having troble getting my nextjs app to work with getServerSideProps() for server-side-rednering. i tried implemening next-redux-wrapper but the state is empty.
*note: redux works fine while it was running on client side, but now im trying to get the state in getServerSideProps() and pass it into the component, so it renders on the server.
store.js:
const reducer = combineReducers({
productList: productListReducer,
categoryList: categoryListReducer,
})
const middleware = [thunk]
const makeStore = context => createStore(reducer, composeWithDevTools(applyMiddleware(...middleware)))
const wrapper = createWrapper(makeStore, {debug: true})
export default wrapper
reducer.js:
export const productListReducer = (state = { products: [] }, action) => {
switch (action.type) {
case HYDRATE:
return {...state, ...action.payload}
case 'PRODUCT_LIST_REQUEST':
return { loading: true, products: [] }
case 'PRODUCT_LIST_SUCCESS':
return { loading: false, products: action.payload }
case 'PRODUCT_LIST_FAIL':
return { loading: false, error: action.payload }
default:
return state
}
}
_app.js:
import wrapper from '../redux/store'
function MyApp({ Component, pageProps }) {
return (
<Component {...pageProps} />
)
}
export default wrapper.withRedux(MyApp)
index.js:
import wrapper from '../redux/store'
export const getServerSideProps = wrapper.getServerSideProps(store => ({req, res}) => {
const state = store.getState()
const { products } = state.productList
return {props: {products: products}}
})
export default function Home({products}) {
return (
<>
<div>{products}</div>
</>
)
}
page.js:
const mapDispatchToProps = (dispatch) => {
return {
listProducts: bindActionCreators(listProducts, dispatch),
listCategories: bindActionCreators(listCategories, dispatch)
}
}
function mapStateToProps(state) {
return {
products: state.productList.products,
loading: state.productList.loading,
categories: state.categoryList.categories,
loadingCategory: state.categoryList.loading
}
}
CategoryScreen.getInitialProps = wrapper.getInitialPageProps((store) => async () => {
await store.dispatch(listProducts())
await store.dispatch(listCategories())
})
export default connect(mapStateToProps, mapDispatchToProps)(CategoryScreen)
reducer.js:
import { HYDRATE } from "next-redux-wrapper"
export const categoryListReducer = (state = { categories: [] }, action) => {
switch (action.type) {
case HYDRATE:
return {...state, ...action.payload}
case 'CATEGORY_LIST_REQUEST':
return { loading: true, categories: [] }
case 'CATEGORY_LIST_SUCCESS':
return { loading: false, categories: action.payload }
case 'CATEGORY_LIST_FAIL':
return { loading: false, error: action.payload }
default:
return state
}
}
store.js:
const combinedReducer = combineReducers({
productList: productListReducer,
categoryList: categoryListReducer
})
const reducers = (state, action) => {
if (action.type === HYDRATE) {
const nextState = {
...state,
...action.payload
}
return nextState
} else {
return combinedReducer(state, action)
}
}
const bindMiddleware = (middleware) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension')
return composeWithDevTools(applyMiddleware(...middleware))
}
return applyMiddleware(...middleware)
}
export const makeStore = (context) => {
const store = createStore(reducers, bindMiddleware([thunk]))
return store
}
export const wrapper = createWrapper(makeStore, { debug: true })
The component does not re render after successfully update state in redux
i have tried to do some condition in componentShouldUpdate end up with loading true without change
reducer.js
import * as types from "./actionsType";
const INITIAL_STATE = {
slide_data: [],
error: null,
loading: false,
};
const updateObject = (oldObject, updatedProperties) => {
return {
...oldObject,
...updatedProperties,
};
};
const slideReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case types.SLIDES_FETCH_START:
return updateObject(state, {
error: null,
loading: true,
});
case types.SLIDES_FETCH_SUCSSES:
return updateObject(state, {
slide_data: action.payload,
error: null,
loading: false,
});
case types.SLIDES_FETCH_FAIL:
return updateObject(state, {
error: action.error,
loading: false,
});
default:
return state;
}
};
export default slideReducer;
actions.js
import * as types from "./actionsType";
import axios from "axios";
import { selectSlides } from "./slides.selectors";
export const slidesStart = () => {
return {
type: types.SLIDES_FETCH_START,
};
};
export const slidesSucces = (slides) => {
return {
type: types.SLIDES_FETCH_SUCSSES,
payload: slides,
};
};
export const slidesFail = (error) => {
return {
type: types.SLIDES_FETCH_FAIL,
error: error,
};
};
export const fetchSlides = () => {
return (dispatch) => {
console.log("fetch Start");
dispatch(slidesStart());
axios
.get("http://127.0.0.1:8000/slides/", {
headers: {
"Content-Type": "application/json",
},
})
.then((res) => {
dispatch(slidesSucces(res.data));
})
.catch((err) => dispatch(slidesFail(err)));
};
};
component
class IntroPage extends Component {
constructor(props) {
super(props);
this.tlitRef = React.createRef();
this.titlelRef = React.createRef();
this.subTitleRef = React.createRef();
this.showcase = React.createRef();
}
componentDidMount() {
this.props.fetchSlides();
}
render() {
const { slides, loading } = this.props;
if (loading) {
return <h1>Loading</h1>;
}
return (
<div className="intro">
<div className="wrapper">
{slides.map((data) => (
<SwiperSlides data={data} key={data.name} />
))}
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
loading: state.slides.loading,
error: state.slides.error,
slides: state.slides.slide_data,
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchSlides: () => dispatch(fetchSlides()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(IntroPage);
Register the redux-logger correctly. The data was returned but nothing changes when I do redux-persist and try to reload data come through
update ::
when I change the size of the browser data it correctly appears what is this !!
update : this problem related to swiperjs
and the solution will be like that:
1 - assign swiper instance to React.CreateRef(null) : this.swiper = React.CreateRef(null)
2 - in componentDidUpdate() make a swiper update : this.swiper.current.update()
4 - use a arrow function syntax in swiper on functions to refer to the outer scope
I can't use default state value in redux
Hello,
I have a function to dispatch Login action,
I want in the initial to be false,
but when I put this value in the render method, it's given me an error
can't read property 'isLogin' of undefined
although in the reducer i add an initialState
let initialState = {
isLogin: false,
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case IS_LOGIN:
state = {
...state,
isLogin: true,
};
break;
default:
return state;
}
return state;
};
here's Store
const store = createStore(
combineReducers({
user: userReducer,
count: countPlayReducer,
}),
);
Action
export const isLoginFunc = isLogin => {
return {
type: IS_LOGIN,
payload: isLogin,
};
};
UI/Dispatching
import {isLoginFunc} from '../../redux/actions/isLoginAction';
signIn = async data => {
this.setState({loading: true}); // maybe here the wrong?
API.post('/login', data)
.then(async response => {
let {
data: {
data: {
response: {token},
},
},
} = response;
this.props.dispatch(isLoginFunc(true));
await saveToken('id_token', token);
this.setState({loading: false}, () =>
this.props.navigation.navigate({
key: 'TabHome',
routeName: 'TabHome',
}),
);
})
.catch(error => {
console.log(error);
this.setState({loading: false, error: error.response.data});
});
};
render(){
...
<Text>{this.props.user.isLogin}</Text>
...
}
mapStateToProps = state => {
return {
isLogin: state.user,
};
};
export default connect(mapStateToProps)(Login);
It looks like you're mapping redux state using the following:
mapStateToProps = state => {
return {
isLogin: state.user,
};
};
But then you're trying to access isLogin via:
this.props.user.isLogin
Looks like this should be changed to:
this.props.isLogin.isLogin
However you might want to alter your mapping to the following instead:
mapStateToProps = state => {
return {
isLogin: state.user.isLogin,
};
};
So that you can simply use:
this.props.isLogin
I'm new to Redux. And I'm trying to create a simple FETCH_ALL_POSTS.
actions
export const fetchPosts = () => async dispatch => {
const response = await jsonPlaceholder.get('/posts');
console.log(response.data)
dispatch({
type: FETCH_ALL_POSTS,
payload: response.data
})
}
posts reducer
export default (state = {}, action) => {
const { type, payload } = action;
switch (type) {
case FETCH_ALL_POSTS:
return {
...state, payload
}
default:
return state
}
}
post list component
const mapStateToProps = state => {
console.log(Object.values(state.posts))
return {
posts: state.posts
}
}
This is working but the data that I'm getting from mapStateToProps is not what I'm expecting.
Result : "array: [ 0:[{},{},{}] ]"
My expected result: "array:[{},{},{}]"
Try this,
const initialState = {
posts: '',
}
export default (state=initialState, action) => {
const { type, payload } = action;
switch (type) {
case FETCH_ALL_POSTS:
return{
posts:state.posts=action.payload.posts
}
default:
return state
}
}
I have a problem with Redux doesn't update the state. Component gets right initial state. Action is dispatched right, data is fetched right and is accesible in action payload inside reducer. Reducer is executing, right case in switch is picked. Just new state doesn't appear in component. I have three others components where it works just fine, only this one cracks.
component
import fetchLinksPage from '../state/links/actions'
...
let Links = ({linksPageLoaded, linksPage, fetchLinksPage}) => {
useEffect( () => {
if(!linksPageLoaded) {
fetchLinksPage()
console.log(linksPage)
}
},[])
return ( ... )
}
const mapStateToProps = ({linksPageReducer}) => {
return linksPageReducer
}
const mapDispatchToProps = dispatch => {
return {
fetchLinksPage: () => dispatch(fetchLinksPage())
}
}
Links = connect(mapStateToProps, mapDispatchToProps)(Links)
actions
// action types
export const GET_LINKS_PAGE = 'GETLINKSPAGE'
export const LINKS_PAGE_LOADED = 'LINKSPAGELOADED'
export const LINKS_PAGE_ERROR = 'LINKSPAGEERROR'
// action creators
export const getLinksPage = () => {
return {
type: GET_LINKS_PAGE
}
}
export const linksPageLoaded = (data) => {
return {
type: LINKS_PAGE_LOADED,
payload: data
}
}
export const linksPageError = (error) => {
return {
type: LINKS_PAGE_ERROR,
payload: error
}
}
const fetchLinksPage = () => {
return dispatch => {
dispatch(getLinksPage())
fetch('http://portfolio.adamzajac.info/_/items/links?fields=*,logo.*.*')
.then(response => response.json())
.then(data => {
dispatch(linksPageLoaded(data.data))
})
.catch( error => {
dispatch(linksPageError(error))
})
}
}
export default fetchLinksPage
reducer
import * as actions from './actions.js'
const linksPageReducer = (state={}, action) => {
switch (action.type) {
case actions.GET_LINKS_PAGE:
return { ...state, linksPageLoading: true }
case actions.LINKS_PAGE_LOADED:
//console.log('update state')
return { ...state, linksPage: action.payload, linksPageLoading: false, linksPageLoaded: true }
case actions.LINKS_PAGE_ERROR:
return { ...state, linksPageError: action.payload, linksPageLoading: false}
default:
return { ...state, linksPageLoading: false, linksPageLoaded: false, linksPage:[], linksPageError:''}
}
}
export default linksPageReducer
store
import aboutPageReducer from './state/about/reducer'
import projectsPageReducer from './state/projects/reducer'
import skillsPageReducer from './state/skills/reducer'
import linksPageReducer from './state/links/reducer'
const rootReducer = combineReducers({
aboutPageReducer,
projectsPageReducer,
skillsPageReducer,
linksPageReducer
})
const store = createStore(
rootReducer,
applyMiddleware(thunk)
)