I learn react JavaScript and now I have a question about React Redux .
I have a component that listen to a Redux store value that is galled newTag
Here is the Component:
/*
* Component handles creating new Tags
*/
class AddTag extends React.Component {
constructor(props) {
super(props);
this.state = {
tagName: '',
categoryName: '',
};
}
submit = () => {
const { tagName, categoryName } = this.state;
const { tagsTag, tagsCategories } = this.props;
// Test if the tag is already created
const result = tagsTag.find(tag => tag.name === tagName);
if (result) {
if (result.category.name === categoryName.name) console.log('jj');
}
const { saveTag } = this.props;
saveTag(tagName.trim(), categoryName);
};
changeCategoryName = categoryName => {
this.setState({
categoryName,
});
};
changeTagName = tagName => {
this.setState({
tagName,
});
};
render() {
const { classes, tagsCategories, isSavingNewTagStarted, newTagErrMsg, newTag } = this.props;
const { tagName, categoryName } = this.state;
return (
<Container className={classes.root}>
<Typography className={classes.typography} gutterBottom variant="h6" align="left">
Type the new Tag name and select the Tag category
</Typography>
<div>
<TextField
className={classes.tagTextField}
id="outlined-basic"
label="New Tag Name"
placeholder="New Tag Name"
variant="outlined"
value={tagName}
onChange={e => this.changeTagName(e.target.value)}
autoComplete="off"
InputProps={{
className: classes.inputBackground,
}}
InputLabelProps={{
className: classes.inputLabel,
}}
/>
<FormControl>
<InputLabel id="category-select">Category</InputLabel>
<Select
className={classes.selectInput}
labelId="category-select"
id="demo-simple-select-helper"
value={categoryName}
onChange={e => this.changeCategoryName(e.target.value)}
>
{tagsCategories &&
tagsCategories.map((element, index) => {
return element.name !== 'All Tags' ? (
<MenuItem value={element} key={element.id}>
{element.name}
</MenuItem>
) : null;
})}
</Select>
</FormControl>
<Button
className={classes.button}
onClick={() => this.submit()}
variant="contained"
color="primary"
disabled={!tagName || !categoryName}
>
Save Tag
</Button>
{newTagErrMsg && <p className="error">{newTagErrMsg.message}</p>}
{newTag && <p>New Tag was saved!</p>}
</div>
<div>{isSavingNewTagStarted ? <Dots /> : null}</div>
</Container>
);
}
}
const mapDispatchToProps = dispatch => ({
saveTag: (name, category) => dispatch(saveNewTag(name, category)),
});
const mapStateToProps = state => {
return {
tagsCategories: state.global.tagsCategories,
tagsTag: state.global.tags,
isSavingNewTagStarted: state.global.isSavingNewTagStarted,
newTagErrMsg: state.global.newTagErrMsg,
newTag: state.global.newTag,
};
};
const enhance = compose(withStyles(styles), connect(mapStateToProps, mapDispatchToProps));
export default enhance(AddTag);
When a new Tag is saved this code line is true:
{newTag && <p>New Tag was saved!</p>}
problem is that the newTag
from Redux store is after the new tag is saved, always true.
So this means that the text "New Tag was saved" is then always visible.
I wonder about a way to reset the Redux store newTag
so the text "New Tag was saved" is not showed after some render later.
newTag
like 'nothing' (it is not used anywhere else)localstorage
variable to use and test for if newTag
is same as before then the "New Tag was saved" will not be showed.Is there some Redux way method I have missed maybe?
Here is the reduces following well known praxis I think.
import { globalActionTypes } from './global.types';
const INIT_STATE = {
tags: [],
tagsCategories: [],
isSavingNewTagStarted: false,
newTag: '',
newTagErrMsg: '',
};
const globalReducer = (state = INIT_STATE, action) => {
switch (action.type) {
// SET_TAGS_ADDED
case globalActionTypes.SET_TAGS:
return {
...state,
tags: action.payload,
};
// SET_TAGS_CATEGORIES
case globalActionTypes.SET_TAGS_CATEGORIES:
return {
...state,
tagsCategories: action.payload,
};
// ADD_NEW_TAG
case globalActionTypes.ADD_NEW_TAG_START:
return {
...state,
isSavingNewTagStarted: true,
};
case globalActionTypes.ADD_NEW_TAG_SUCCESS:
return {
...state,
isSavingNewTagStarted: false,
newTag: action.payload,
};
case globalActionTypes.ADD_NEW_TAG_FAILURE:
return {
...state,
isSavingNewTagStarted: false,
newTagErrMsg: action.payload,
};
default:
return state;
}
};
export default globalReducer;
Some users prefer to keep every single piece of data in Redux, to maintain a fully serializable and controlled version of their application at all times. Others prefer to keep non-critical or UI state, such as “is this dropdown currently open”, inside a component's internal state. Using local component state is fine.
Redux Persist is a popular library which lets you add persistence to the store. The library will automatically save the store each time the state updates. You don't need to write any persistence code in your actions or reducers. You now need to connect the library to your store.
Even though the array might contain the exact same object references each time, the array itself is a different reference, so the shallow equality check fails and React Redux would re-render the wrapped component.
React-redux component does not rerender on store state change.
It is used to manage the state of data and access them at different components level in the app. In redux, there are three parts as follows: Store: It is an object which provides the state of the application. This object is accessible with help of the provider in the files of the project.
Redux doesn't have a Dispatcher or support many stores. Instead, there is just a single store with a single root reducing function. As your app grows, instead of adding stores, you split the root reducer into smaller reducers independently operating on the different parts of the state tree.
React Redux's <Provider> component uses <ReactReduxContext.Provider> to put the Redux store and the current store state into context, and connect uses <ReactReduxContext.Consumer> to read those values and handle updates. The useStore hook returns the current store instance from the default ReactReduxContext.
React Redux provides APIs that allow your components to dispatch actions and subscribe to data updates from the store. As part of that, React Redux abstracts away the details of which store you are using, and the exact details of how that store interaction is handled.
Just dispatch an action to clear newTag
. No need to ruminate over it.
As of good practices, will not recommend changing the redux store for the manipulation of UI of the app. Redux should store data to be displayed.
Solution for the above case can be done in the following way:
In this way, we are not changing anything in redux and are also able to solve the issue by changing the code on the component level.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With