Setting initial state from Redux - reactjs

I have stored username, full name & email address in redux store. I have a component that needs the email address so it can make an API call to obtain the users group information (using domain - i.e chase#gmail.com becomes the key for the database query using gmail.com). The component is connected to the store and uses mapStateToProps to obtain state information.
Is it an anti-pattern to do something like this in this.stat = { }
this.state = {
group: '',
owner: this.props.user.id,
domain: this.props.user.email.split('#')[1],
errors: {},
}
Thank you for all the suggestions.

Its not good practice to duplicate redux state in the local state.
Why? Because it is not scalable. Imagine if you r data will be need to change. So you will need to update both your local state and redux state. And also, if your redux state will change - you need to update local state. It will becomes to spaghetti.
What you can do?
You can just use only your data from props. Implement shouldComponentUpdate method to be sure, that your data will be always up-to-date.
shouldComponentUpdate(nextProps, nextState) {
return this.props.user !== nextProps.user
}
And use the data from the props.

I prefer to use them based on my thumb rule.
If you need the data be instance specific - use state.
Example: you have a button group component, keep the data in state since there is a possibility of multiple usage of the component.
If your data is required to be global, so that anyone can modify it from any other component, and specially if you want the data to be tied in to an external source, use Redux state. Since the data is external to your component, it becomes damn simple to manage it.
Link: https://github.com/reactjs/redux/issues/1287

Related

Should i update reducers state for specific component or manage in component state?

In my project i normally get data from reducers and pass data to component, in that component if data is to be updated e.g
obj :{ age:20, name: 'hassan' }
for any update action than i create copy of this object to my own state in constructor as
this.state {
obj : this.props.obj
}
then utilize copied obj and send to service for update actions to server side etc.
but i never update reducers object instead always create component own state.
I am new to react please guide me should i update reducers object and further utilize it instead to create own state for component and if i should update reducers object it effects permormance or currently pattern i am following is better or not ?
The concept of redux comes down to maintaining a global state that can be accessed by any component.
The usage of the store differs based on the variable you are storing. It is recommended to store only the values which are being used by other components .If that's not the case you can maintain the state in indvidual react components.
redux store vs react state this tutorial gives a handfull experience to choose wisely

React global state update local state

I need to update the local state after a global state is updated.
I tried mapStateToProps but this only maps the global state into the component, it does not update the local state.
Please refer to image to see the code.
after mapStateToProps is updated, the values on the selected_smsf_member should be parsed into the local state which is used to create the form.
I am also open to suggestions of a better approach. Basically what I am trying to do is to show the details of a selected member on a previous component.
As you can see mapStateToProps, its name says everything, It will map state to props, you can access its variable in your props, like this.props.selected_smsf_member in your component. If you still want to update your local state, using getDerivedStateFromProps(), but read this blog first: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
You could utilize getDerivedStateFromProps. You can check your props and derive state from it when they change. A few notes though:
You should initialize your state.memberDetailsForm as a falsey value and check that in your getDerivedState function otherwise it'll derive your state EVERY TIME the props change which would lead to unexpected consequences.
I don't know the exact mappings to your code so don't just copy the
example below and expect it to work.
Implementing this method should get you the output that you want.
static getDerivedStateFromProps(props, state) {
if (!state.memberDetailsForm) {
return { memberDetailsForm: props.selected_smsf_member }
}
}

Reactjs accessing state of another component

Basically, I have a component called Timeperiod which is a dropdown where users will select values such as "today", "yesterday", "last week", etc.
I want to re-use the <Timeperiod> component in a lot of other components and the problem is I wouldn't be able to access which value they chose if I call it in another.
I know an alternative would be to call my other components inside of Timeperiod and passing them properties based on Timeperiod state but wouldn't that mean I need to create multiple Timeperiod like classes?
Would redux or something be a good way to handle these situations?
Here's my codesandbox: https://codesandbox.io/s/ypyoq8zoz
Right now I only have App.js calling Timeperiod, but I will have many more classes calling it too. I want to be able to access the date chosen in App.js while making the Timeperiod class re-usable.
To decide if you need Redux and how much of Redux do you need, you have to consider carefully the whole application you are developing. Redux adds some boilerplate, which might be too much for the benefits you would gain.
You can however solve your problem without Redux.
Without Redux
One of the key ideas under React is called "Lifting state up". This means that if several components need access to the same piece of data, you should definitely move the storage of that piece of data in a component that is a common ancestor of all those components (see https://reactjs.org/docs/lifting-state-up.html).
In your case, it should not be responsibility of Timeperiod to keep memory of the selected date, but of App (indeed, the closest common ancestor of all components that need access to the selected period). Timeperiod should take the selected date from app via a property, and notify App when user changes the selected date using an event (again, a prop containing a function).
class App {
constructor(props) {
super(props);
this.state = {
start: new Date(), // initial value
end: new Date(), // initial value
}
}
render() {
return (
<Timeperiod
start={this.state.start}
end={this.state.end}
onStartChange={newValue => this.setState({ start: newValue })}
onEndChange={newValue => this.setState({ end: newValue })}
/>
);
}
}
With Redux
Redux allows you to keep a global state and access it in special components called Containers. You can put how many containers you want, in any point of the document tree. This seems great, but has several drawbacks:
Too many container components degrade performance
Having full access to whole state in any point of the tree could create problems if you are not super careful. A component could modify some data it should not be allowed to access, and so on.
Redux introduces some boilerplate that might be too much if the application is simple
For any update you have to define some actions capable of handling it, create a reducer to produce the next state from the previous state and the action, and connect together all these pieces
Conclusion
It really depends on your application whether Redux is good or bad, but if your component hierarchy is not too deep and your app not too complex, vanilla way could be better
So, to follow up our comments. Here's how you could approach it:
The Timeperiod component expects a getDate function that expects a title argument. When you render the Timerperiod component, each time it has a separate state and props.
Check out how I rendered more than one(in the app.js), to show that in action.
Using redux what you could do is have a within your state a timePeriod sub state handled by a dedicated reducer which stores the user's choice.
Then each of your TimePeriod component will be hooked to this state using something like
const ConnectedTimePeriod = connect(
state => state.timePeriod,
{
onTimePeriodChoose (timePeriod) {
return {
type: "CHOOSE_TIME_PERIOD",
timePeriod
}
}
}
)(TimePeriod);
Which hydrates your component with the global shared state and provides a function as a prop to update the time period.
The ConnectedTimePeriod can then be used everywhere and will share the global state.
I would suggest you take a look at the react-redux docs for example and details.

Putting props to state in react

I'm working with react-redux in a current project and on my search for react wisdom I came across a 'convention' I don't understand.
Other programmers tend to put a prop to state right in the constructor. Why is that?
I've never seen it in the official documentation and from there I learned that these two are two different things to hold and share data.
Is there any use in it or mybe just a personal preference?
Thanks.
It sounds like a pattern for when you need some initial value from outside the component, but then want to either ignore, or not immediately affect, the outside (by for example dispatching Redux actions on each value change).
For example, maybe you have a form that should be prefilled with some values that the component gets from the outside (Redux state) through mapStateToProps or similar. You could let every form fields onChange dispatch an action that changes the Redux state, causes the incoming props to change, and then re-render the form with the new value. Or maybe you find that to be overkill. Maybe you're satisfied with keeping the changing form data in the component internal state until the user actually submits the form, and only then dispatch an action that will post the form data, change the Redux state and pass new props (like success status) down to the form component.
Yes, it is possible, especially when you want to keep things simple by not using container components or flux / redux store to manage application's state.
A component can manage its own state, and the initialState will be assigned as the props passed from its parent component.
Consider the following example:
class TodoList extends React.Component {
constructor(props) {
// Assign todos property to state so that the TodoList component
// can self-manage this value without interacting with outside components.
this.setState({ todos: props.todos });
}
...
addTodo(todoDescription) {
this.setState({ todos: this.state.todos.concat[todoDescription] });
}
}
However, I still do recommend to separate the view components and data manipulating components when your applications is complex.

ReactJS controlled component and immutable data

I wonder how
controlled components (e.g an input box) can be implemented, if the data of an app is build upon immutable data and the app uses "===" equality operators in shouldComponentUpdate() for fast re-rendering.
Let's assume deeply nested data and a controlled component somewhere deep in the hierarchy:
When local component state is used (setState()) as one would implement this normally, the changes are not seen by react as the component hierarchy rendering process might skip branches, because the immutable data has not changed. To avoid this, all local component state has to live in the application state, and every event on the controlled component (e.g. typing in an input box) has to result in changing the immutable data.
Although this should work, is this the (only) way controlled components are implemented when immutable data is used??? Doing this all with flux (fire an action, fetch the store data...) might be a lot of overhead/round-trips for something simple as typing into an input box.
A component's state is a great place to put data you don't need to persist or access from multiple places. A common example of this, is an unsubmitted form. When the user does submit the form, you can then pass the local state upwards (callbacks in props) or horizontally (actions, event emitters, apis, etc.).
Also, about not updating, the only time calling setState won't trigger an update in the same component is if you have a overly negative shouldComponentUpdate. If you need local state, the shouldComponentUpdate should take that into account.
There is often a trade-off between placing state to a store or hold it locally. Both approaches work well with immutable collections.
The local state is handled using setState, no direct this.state access. JS strings are immutable, so nothing to care about
onChange: function(event) {
this.setState({value: event.target.value});
}
Sending to a store is almost the same:
onChange: function(event) {
var flux = this.getFlux();
flux.actions.setSomeValue(event.target.value);
}
Store gets the actions and do update/updateIn in immutable collection

Resources