Putting props to state in react - reactjs

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.

Related

Why is redux state not mapped to react state?

I am very very new to React-Redux and encountered a method called mapstatetoprops.
However why is redux state not mapped to react state ? Why is it mapped to props instead ?
In React, state belongs to the component while props are passed to the component from it's parent. mapStateToProps() is a function that is used inside connect() to pass data from the Redux store to a component.
The difference between state and props: https://codeburst.io/react-state-vs-props-explained-51beebd73b21
If you want to use data from the Redux store in a component's state, the component would first need to receive it as a prop. You would then be able to map it to the component's state in getDerivedStateFromProps. https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
When you derive state from props this way, updating the component's state does not change the Redux state.
The primary reason (as I see it):
"Dumb" components deal only with properties, not state.
One motivation for "dumb" components is that they're trivial to test: all you need to do is pass in props. This means that regardless of where the props come from the only thing you're testing is that they do the Right Thing with whatever props they're given.
Mapping the redux store to properties reinforces this notion. Once you introduce component state you then have to play more (some easy) games to test the component, but it's not as straight-forward as a pure component.
Cause this is the Redux workflow.
When without redux you use local state (component state) and passes data through parent to children, this makes data sharing very difficult when you have more components.
ComponentOne have data to be passed to component 4:
ComponentOne -> ComponentTwo -> ComponentThree -> ComponentFour
With Redux, you have a store, but can't use is as a object (getters and setters), you map it's contents to the components that needs each property.
Redux scenario:
store {userName: "user", otherData...}
Dashboard
function mapStateToProps(state) {
return {
userName : state.userName
}
This way the component will listen to userName changes, but only can change data in the store through the mapDispatchToProps. This way, the Single Source of Truth React principle is assured.

What is the life cycle of a React component in context of Redux?

I'm trying to restructure my React app around Redux, and getting confused.
one site says:
Components receive props from their parent. These props should not be
modified inside the component.
another says:
You used to be able to change props with setProps and replaceProps but
these have been deprecated. During a component’s life cycle props
should not change (consider them immutable).
So I should consider props to be immutable over a component's lifetime. OK, then, the alternative is state (React state, which I understand is a very different thing from Redux state. OK...)
React state is the mutable state of the component. It belongs to the component and, unlike props, can change during the component's life cycle. OK. Outside of the context of Redux, I totally get that. Each component owns its own mutable state and passes what it needs to down to its children as props, which are for the children immutable. When the state changes it will cause the component to re-render its children, giving them new props as needed.
Now introduce Redux. The Redux store holds a single state for the entire app. Does this now replace any React state? Are all of the elements of the Redux state delivered to React components as props? There is mapStateToProps which seems to suggest this. So can I now forget about React state entirely?
I think of the component life cycle as lasting, say, as long as the user can see the thing on screen. But if props can't change during the component life cycle, and everything is now (from the React perspective) props - does that mean the life cycle is only as long as it takes Redux to refresh its store?
As pointed out by Dan Abramov in his famous You might not need redux article,
Redux should be used only when you need persistence across the application. When data is ephemeral (think about a selected accordion opened in a simple view) you can safely store your state in a local state.
So:
Does this now (Redux) replace any React state?
If you wish, yes. But it isn't mandatory.
Are all of the elements of the Redux state delivered to React components as props?
Usually, yes.
So can I now forget about React state entirely?
Yes, you can. Although is not mandatory and local/redux state can live happily together.
[...] does that mean the life cycle is only as long as it takes Redux to refresh its store?
Renders occurs as any state (local or redux) changes.
Lucy Bain's post is good as an explainer, but note that the mentions of setProps refer to a very old version of React, and the linked release notes for React 0.14 describe those as only having been useful for updating the top-level component in an app. Today, if you actually need to update the props for the root component, you'd call ReactDOM.render(<MyApp newProp={123} />) a second time.
See the Redux FAQ entry on splitting state between Redux and React components for some rules of thumb to help decide where each piece of state should live.
I'd also encourage you to read through the React-Redux documentation as well to understand how they fit together.
I think what you need to understand first is the Redux cycle which goes like this:
Action Creator->Action->dispatch->Reducers->State
An Action Creator is a function that will return a plain JavaScript object referred to as the Action. The action will have a type and payload that provides context on what its doing, for example, creating an insurance policy, it would look like so:
// People dropping off a form (Action Creator)
const createPolicy = (name, amount) => {
return { // Action(a form in this analogy)
type: 'CREATE_POLICY',
payload: {
name: name,
amount: amount
}
};
};
All action creators look identical to what you see what here with some small variation.
But I know the question is understanding the cycle and their purposes not so much the syntax.
So you want to understand what role your action creators need to play in your React app and then on to your Reducers and figuring out their role, but really after you've figured out the hard part, the Action Creators, the rest start to fall into place.
The dispatch receives the action and dispatches it out to all the different Reducers. dispatch is part of the Redux library itself, so you don't need to write it out and your question regarding mapStateToProps if you tie it in with the higher order component utilizing the connect() helper, that whole process is like a manual override of the dispatch process.
The idea behind Reducers is that we write out functions and each one models a different behavior inside the application. Each reducer gets called with an Action, the reducer inspects the action and determines whether to modify behavior based on that action.
So action creators are like people filing an insurance claim and the action is the actual claim. Those claims go to these different departments called reducers.
So keeping to this analogy of insurance claims, a reducer I may want to create would be a claims history reducer like so:
// Reducers (Departments)
const claimsHistory = (oldListOfClaims, action) => {
};
So the reducers' job is to determine whether or not it cares about the type of action it is receiving. If it is of type createClaim then we want to ensure the code inside the function pulls off the payload property and add it to the list of claims, if not then return list of claims unchanged and that would look like so:
// Reducers (Departments)
const claimsHistory = (oldListOfClaims, action) => {
if(action.type === 'CREATE_CLAIM') {
// we care about the action (claim)
return [...oldListOfClaims, action.payload]
}
// we dont care about the action (form)
};
So I am just using ES2015 syntax which takes an array, take all of the records and add them to a brand new array and add the new record of action.payload.
Its the equivalent to doing const numbers = [1,2,3] and then [...numbers, 4] which outputs:
(4) [1, 2, 3, 4]
Or the equivalent of oldListOfClaims.push(action.payload); but there is a distinct difference between this one and the one I used.
In the syntax I used for the reducer I am creating a brand new array and adding records to it, whereas the push() method is modifying an existing array.
We always want to avoid modifying existing data structures inside a reducer. You will never see push() inside a reducer.
Then there is the case where we don't care about the action:
// Reducers (Departments)
const claimsHistory = (oldListOfClaims, action) => {
if(action.type === 'CREATE_CLAIM') {
// we care about the action (claim)
return [...oldListOfClaims, action.payload]
}
// we dont care about the action (form)
return oldListOfClaims;
};
Next, you need to handle the case where the very first time a reducer gets called, there will be no data to passed to it. We will essentially receive the value of undefined. We need to default the value of the first argument.
// Reducers (Departments)
const claimsHistory = (oldListOfClaims = [], action) => {
if(action.type === 'CREATE_CLAIM') {
// we care about the action (claim)
return [...oldListOfClaims, action.payload]
}
// we dont care about the action (form)
return oldListOfClaims;
};
So undefined got replaced with an empty array.
So figuring out your actions and reducers is the hard part when implementing Redux as well as the fine grain rules that go with it such as making sure you don't modify the array that gets passed in and ensuring you always return some value.
The overall goal of a reducer is to take some existing data passed to it as an action and find and return that existing data based upon the contents of an action.
So this is all the baseline stuff to get you started. Out of all this is where you want to return a new instance of a Redux store.
Depending on your project you may have 1 to 3 or more action creators and reducers. You then wire all these up into a single object called a store which is just an assembly of different actions and reducers.
So somewhere in your components you are going to be adding something like this: const { createStore, combineReducer } = Redux;
This is what your combineReducers looks like:
const ourDepartments = combineReducers({
accounting: accounting,
claimsHistory: claimsHistory,
policies: policies
});
Then you complete creating your store like so:
const store = createStore(ourDepartments);
store;
The store represents the entire Redux application. It contains references to all your different reducers and to all your state produced by those reducers or data.
The store object has some useful functions such as the dispatch function. In order to call dispatch() we have to pass in an action created by an action creator and then pass it off to store.dispatch().
const store = createStore(ourDepartments);
const action = createPolicy('Alejandra', 35);
console.log(action);
store.dispatch();
When you console log out action you should see you have the type of action and your payload:
{type: "CREATE_POLICY", payload: {…}}
You then take that action and pass it to store.dispatch() like so:
So far you probably saw an error saying that Action must be a plain JavaScript object and so on, well this error will go away once you pass in the action like so:
store.dispatch(action);
You can check to see the state of the application print out like so:
console.log(store.getState());
{accounting: 135, claimsHistory: Array(0), policies: Array(1)}
accounting: 135
claimsHistory: []
policies: ["Alejandra"]
proto: Object
Now you can start passing in the actions like so:
store.dispatch(createPolicy('Alejandra', 35));
store.dispatch(createPolicy('Ben', 20));
store.dispatch(createPolicy('Daniel', 78));
store.dispatch(createClaim('Alejandra', 120));
store.dispatch(createClaim('Ben', 50));
store.dispatch(deletePolicy('Daniel'));
console.log(store.getState());
Output in console:
{accounting: 63, claimsHistory: Array(2), policies: Array(2)}
accounting: 63 claimsHistory: Array(2) 0: {name: "Alejandra",
amountOfMoneyToCollect: 120} 1: {name: "Ben", amountOfMoneyToCollect:
50} length: 2
proto: Array(0) policies: Array(2) 0: "Alejandra" 1: "Ben" length: 2
proto: Array(0)
proto: Object
So thats how the Redux library works
Alright, so I showed you how it works on its own, but how do the two libraries, Redux and React interact with each other?
So yes, with the implementation of Redux, we make use of component level state, much less frequently. We generally store all of our data inside of Redux instead.
There are some scenarios where we want to have state inside of both Redux and React components, but in general all your state inside of React app is now inside of Redux instead, so that translates into a much more simple React application.
Lets say you had some iTunes type of app, how would we put it together with just Reactjs?
So this would be your app without redux:
So here your SongDetail only needs to know what your currently selected song is. So your App component passes it down to SongDetail as a prop and the SongDetail would render it out to the screen.
With React alone this would be a simple and straightforward application.
So how does your application change with Redux?
So just as before, we are going to have an App component, a SongList and SongDetail, but the App component is going to be passing down very little information down the SongList and SongDetail.
Instead, we are going to abstract out these ideas of creating a list of songs and selecting a song and what the currently selected song is into a redux application.
So you would have a reducer that will produce a list of songs and a reducer that records what a currently selected song is. Those are the two pieces of state in your application.
Finally, we are going to ensure we have an action creator to somehow change your state. That is the only way you change your state inside a redux app.
So your action creator may be called select song, that will dispatch an action and tell the selected song reducer to update its data and reflect the new currently selected song.
So thats your app with Redux.

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.

React props states and Redux

What is the different between states and props?
How can you pass a value of let's say CompomentA to ComponentB if we have have for example ComponentA which takes an input then ComponentB is suppose to output(to print it on the screen) that same value if we have a third component called CompomentContainer which is a container of both A and B?
What is Redux? the definition of redux on the main website does not make sense to me. How does it work exactly? How is it useful to react?
Please bear with me, I hope my questions make sense. Thank you.
Those are very valid questions. I've been there and I know how frustrating it is to read about redux and not understanding anything. For some reason people like to use fancy words, which sounds complicated but in reality things are very simple and easy.
What is Redux?
Redux is a Flux architecture. In simple words it will help you to manage the global state of your app.
How does it work exactly?
Redux will create a single "store", this store will have all the data that you need to render in your components, you can update the data using "actions", you will call the actions from your components, these actions will transfer the new data to the "reducers", inside of a reducer you will basically copy the data from the components to the global state (reducers should be pure functions).
How is it useful to react?
It's very useful! Mainly because you will be able to share data across components. Also by having a global state you could save it to the local storage (or a database) to add offline support.
What is the different between states and props?
You can define props to describe the properties that the component will receive when creating instances, you can think of props like parameters, for example:
<MyComponent name="Crysfel" lastname="Villa" />
The previous component is receiving two props, name and lastname. Props will allow you to send data from ComponentA to ComponentB, assuming ComponentB is a child of ComponentA. Props will also help you to receive data from redux. As a rule of thumb, you should never modify the value of the props, these values are just to receive data.
State on the other hand is an object that might contain configurations for your component, the idea is to handle the state of the component, for example a collapsible container, you could have a toggle property in the component's state and toggle the value when user clicks a button. However when using redux you will rarely use the component's state, because Redux is managing the state of your app.
For your second question about sending data between component, you would use redux for that, ComponentA should call an action and send the new data to the global state, then redux will update your component with the new data and then you can render the new data into ComponentB (using props).
What is the different between states and props?
State is data that is tied directly to the React component in which it is set. Props is data that is passed into a child component from the parent component. Unlike state, props are immutable and never "set" directly.
How can you pass a value of let's say CompomentA to ComponentB if we have have for example ComponentA which takes an input then ComponentB is suppose to output(to print it on the screen) that same value if we have a third component called CompomentContainer which is a container of both A and B?
To pass value from Component A to ComponentB you would provide the value as props, passed in via the ComponentA render function. Something like this:
class ComponentA extends React.component {
render() {
return <ComponentB myvalue={value} />
}
}
In ComponentB the value can be accessed: this.props.myvalue
What is Redux? the definition of redux on the main website does not make sense to me. How does it work exactly? How is it useful to react?
Redux is an implementation of the ideas of Flux with a few architectural differences. You can think of it as a library that helps you create a central data store that passes data one-way into React components. It allows you to maintain global state outside of the components themselves.
A top-level container component typically listens to the store and re-renders whenever the store data changes (see the connect function). The data is then passed from the container component into the children components that need that data so they can render properly.

ReactJS: Why is passing the component initial state a prop an anti-pattern?

I've created a small ReactJS dashboard with the help of SocketIO for live updates. Even though I have the dashboard updating, it bugs me that I'm not quite sure if I did it correctly.
What bugs me the most is the Props in getInitialState as anti-pattern post. I've created a dashboard that gets live updates from a server, requiring no user interaction beyond loading the page. From what I've read, this.state should contain things that will determine whether the component should be re-rendered, and this.props.... I don't know yet.
However, when you initially call React.render(<MyComponent />, ...), you can only pass props. In my case, I get all data from the server, so the initial props just end up in this.state anyway. So all of my components have something like this:
getInitialState: function() {
return {
progress: this.props.progress,
latest_update: this.props.latest_update,
nearest_center: this.props.nearest_center
}
}
Which, unless I've misinterpreted the aforementioned blog post, is an anti-pattern. But I see no other way of injecting the state into the Component, and I don't understand why it's an anti-pattern unless I relabel all of my props to prepend initial on them. If anything, I feel like that's an anti-pattern because now I have to keep track of more variables than I did before (those prepended with initial and those without).
Disclaimer: When I answered this question I was learning / trying to
implement vanilla Flux and I was a bit skeptic about it. Later on I
migrated everything to Redux. So, an advice: Just go with Redux or
MobX. Chances are you won't even need the answer to this question
anymore (except for the science).
Passing the intial state to a component as a prop is an anti-pattern because the getInitialState method is only called the first time the component renders. Meaning that, if you re-render that component passing a different value as a prop, the component will not react accordingly, because the component will keep the state from the first time it was rendered. It's very error prone.
And here is what you should do:
Try to make your components as stateless as possible. Stateless components are easier to test because they render an output based on an input. Simple like that.
But hey.. my components data change.. I can't make them stateless
Yes you can, for most of them. In order to do that, select an outer component to be the state holder. Using your example, you could create a Dashboard component that contains the data, and a Widget component that is completely stateless. The Dashboard is responsible for getting all the data and then rendering multiple Widgets that receive everything they need through props.
But my widgets have some state.. the user can configure them. How do I make them stateless?
Your Widget can expose events that, when handled, cause the state contained in Dashboard to change, causing every Widget to be rerendered. You create "events" in your Widget by having props that receive a function.
Ok, so now, Dashboard keeps the state, but how do I pass the initial state to it?
You have two options. The most recomended one, is that you make an Ajax call in the Dashboard getInitialState method to get the initial state from the server. You can also use Flux, which is a more sophisticated way for managing data. Flux is more of a pattern, rather than an implementation. You can use pure Flux with the Facebook's implementation of the Dispatcher, but you can use third-party implementations like Redux, Alt or Fluxxor.
Alternatively, you can pass this initial state as a prop to the Dashboard, explicitly declaring that this is just the initial state.. like initialData, for instance. If you choose this path, though, you can't pass a different initial state to it aftwards, because it will "remember" the state after the first render.
OBS
You are not quite right in your definitions.
State is used to store mutable data, that is, data that is going to change during the component life-cycle. Changes in the state should be made through the setState method and will cause the component to re-render.
Props are used to pass in imutable data to the components. They should not change during the component life-cycle. Components that only use props are stateless.
This is a relevant source on the "how to pass the initial state to components".

Resources