What are props.values in react? - javascript

I have a project with react, redux and redux-form. Playing with redux-form shouldValidate function, I wanted to see what was inside props and nextProps. The default implementation of shouldValidate function handles variables props.values. I wonder what those props.values are? Are they a react thing, redux thing or redux-form related? Where could I find documentation about them? As those values are not something I'm by myself adding in anywhere. I consoled them, and they consisted attributes like source and status:
source: "FORM"
status: "RECEIVED"
Inside the render method of my component, I see no props.values. Only the props I have given to the component myself. But inside the shouldValidate function, there are props.values prop.
EDIT: For those trying to explain basics of props to me:
Do not, I know what props are in react. What I'm asking is what is this particular props.values prop? Where does it come from, as I have not inserted it by myself. Somehow it is related to react, redux and redux-form

Disclaimer: I'm one of the Redux Form maintainers.
The shouldValidate function receives a single parameter params which is comprised of the following documented keys:
values
nextProps
props
initialRender
structure
props/nextProps are a combination of props as documented here + whatever you manually provided to the component (eg <MyForm customProp="bla" />).
Even though such prop values is available (and is in fact something from Redux Form), please don't rely on it.
As you can see, values is undocumented at that page.
Also, there's no need to use something which is undocumented if the documented params of shouldValidate is equivalent.
* If you feel like our docs could be improved to declare "special cased props", go ahead and send us a pull request!

You linked the shouldValidate function documentation. The documentation states that values are redux-form specific, and contains all the filed values your form currently has.
Redux-form keeps track of all the input values you put inside a "Field" tag and keeps it in the redux store.
The props are the properties you define for you own "Form" component. Redux-forms wraps it creating a HOC (higher order component). It passes props in shouldValidate for you to access your props. props.values is an internal representation of filed values, which you should not rely on, the representation may change in the future.

Related

Can state be named differently (with another name like 'globalState') in ReactJS?

I am new to React (just 1 online course) and am discovering the magic of props and state. I realise that props are immutable and state is mutable. I am getting clearer about their uses but there's one point I would like to clarify that I have not been able to find online.
So props can be passed from Parent to Child and when they are passed the name of the variable holding the props can be changed. When state or its values are passed to child components, a mechanism is also passed along to the child to be able to modify the state at the parent level by the child.
I hope this is correct as so far this is what I have understood about props and state.
Now I have a project where I have "App.js" which is the topmost parent with "Home.js" as its child. I plan to use state in both of them. But the state in App.js is something of a global state (and I don't want to use redux) and the state in Home.js would be the state that the application would use for its regular use.
Now both of them are being named using the state={} format (I am using class based components) and referred to as this.state but within their own components, which is working fine.
My question is about the format of naming state as state, is this mandatory or just a standard that developers are expected to follow?
I've tried to change the name of the state and it seemed to work but maybe I did something wrong as I didn't really expect it to work... so that's why I wanted to confirm if it's ok to change the name of state in a component to something like globalState or store
Any advise would be appreciated.
When writing Class Components, you can only update the state using the setState method and it will write the state to the state property.
While I suppose you could add a globalState getter property to the class which returns the value of state, this seems pointless.
Note that storing data in other properties instead of using setState to write to it will not trigger a re-render. You're just writing to a property on the object and not dealing in anything that React considers state.
When writing Function Components, state is handled with the useState hook and the processing of storing the state data is handled by React internals. The state value is then assigned to whatever variable you want to assign it to after reading the returned state array.
const [anyName, setAnyName] = useState(defaultValue);
const [anyOtherName, setAnyOtherName] = useState(otherDefaultValue);

What's the reason for not getting the variable I'm expecting in the functional component?

I'm familiar with useState hook for storing variables that change and need to reload the component. Are variables not local to each function call? For example, I have a functional component that I passed ticket information to. I take that information store it in a variable and pass it to another screen. That component is render in a flat list depending on which one is called I want to store that value and pass it to another screen. My problem is, that value is getting stored in the local object but only the value of the last item rendered not the one pressed. Here is my code:
If I save ticket from params, update it with the "siteCode", and pass it in the params of the onPress event, I don't get the results i'm looking for. If i pass siteCode outside of the custom object I get the results I'm looking for. I just want to understand what I'm missing here. Do i still need to use the useState hook even though i'm not looking to render the component again? Thanks
You are breaking the contract, so unfortunately you get whatever you get. And since it's not a supported use case you sadly can't expect it not to change in different React versions either.
React expects a pure functional component to be, well, a pure, functional, component (referentially transparent, no side effects). You are mutating your props, which as I said is not supported (this seems to come up a lot on github issues on the React repo).
In ye olden days, if your component was not pure you used a class. Now we have hooks, but the hook is essentially a clever workaround: because React knows about the hooks you don't violate the functional component contract. But that doesn't mean anything goes, if you have a side effect (like mutating an object defined elsewhere) then you need to put it in a hook or screwy things will happen.
N.B. even in a class, or even outside of React entirely, it's rarely (never?) a good idea to mutate the parameter to a function unless that mutation is the only thing the function does.

What's the difference between React Context API & Hooks?

As i understand it, they both deal with state. Hooks seem to be more internal to a components state, while the context api seems to solve the problem of prop drilling, creating a more global state? Is this false? What am I missing?
Thanks a lot!
As I understand, they have completely different use cases. Context allows you pass a value deep into the component tree, where the value could be any kind of prop, say, a color. By using context in this way, you avoid having to do props.theme on every component that needs a theme color passed to it.
Hooks, on the other hand, replace the need for classes; instead you create a function and useState enables you to pass in variables. I.e. Hooks allow you to take a React function component and add state to it, and apply lifecycle methods like componentDidMount and componentDidUpdate. This is useful because if you find your function requires state, you don't need to refactor it into a class, you can just add Hooks. :) Of course this choice is contentious among developers though.

Re-rendering of connect()ed component based on mapStateToProps output

In a React + Redux based project, I have a connect()ed component which checks user permissions via an API fetch. Fetched permissions are stored in the Redux store.
The component basically looks like <Can check="...">...</Can>, which talks to our API (via Redux actions) to resolve the check. If the permission is granted, this.props.children is rendered, null otherwise.
For that, mapStateToProps() computes a passes prop from authorization data in the store, which is checked in <Can />s render() method. I utilize the ownProps parameter to mapStateToProps() to get the "stuff to check" and compute the passes flag.
There's a bit of caching going on so I don't re-fetch on every component mount, and it basically works. Sometimes, though, the component will not re-render when the passes prop updates to true (it will however render after navigating away - using react router - and back again, so basically if the component is re-mounted).
Do connect()ed components re-render if the output from mapStateToProps() changes? The docs for react-redux's connect() say this:
If ownProps is specified as a second argument, its value will be the props passed to your component, and mapStateToProps will be re-invoked whenever the component receives new props.
Does that mean that passing in ownProps changes the rendering to only re-render if props change, or in any other way? How can I understand the note regarding memoization/returning a function from mapStateToProps(), or is that not even related?
Thank you
Do connect()ed components re-render if the output from mapStateToProps() changes? The docs for react-redux's connect() say this:
Output from a function can’t change by itself. Something must trigger this function to be re-evaluated in the first place.
If Redux state changes, mapStateToProps is re-evaluated.
If props received from parent component are shallowly unequal (have changed) and you use ownProps argument, mapStateToProps is also re-evaluated.
If mapStateToProps returned shallowly equal values to its last call, then React Redux will skip rendering. If it returned shallowly unequal values, the wrapped component will be re-rendered. It is assumed that mapStateToProps itself is a pure function.
Sometimes, though, the component will not re-render when the passes prop updates to true
Please create a minimal project reproducing this and file an issue with the relevant code example.
How can I understand the note regarding memoization/returning a function from mapStateToProps(), or is that not even related?
Not related.
Several things to know here:
connect will shallow-compare the output of the last mapState call to the current mapState call. If nothing changed, it will not re-render the wrapped component.
By default, connect will only run mapState when the store notifies subscribers. However, if your mapState function is declared as taking two parameters, connect will pass in the wrapped component's props as the second arg, allowing you to do things like state.somePerItemData[ownProps.itemId]. It also then calls mapState any time the incoming props differ, as that may affect the output of mapState.
Reselect's default memoization only keeps a single cached value per selector function. If you have a component that is instantiated multiple times, and all instances are sharing the same selector function instance, then the selector's memoization probably won't work the way you want, because each component instance is probably calling it with different inputs (such as their own props). So, as a heavily advanced optimization, you can actually pass a factory function as the mapState argument, which could create a unique selector function instance for each component instance.
All that said, I'm afraid I don't have a specific answer for your actual question about the component not updated. I'd probably need to see the code in more detail.

ReactJs: How to pass the initial state while rendering a component?

I know I can pass props while rendering a component. I'm also aware of the getInitialState method. But the problem is, getInitialState isn't quite helping because my component doesn't know it's initial state. I do. So I want to pass it while I'm rendering it.
Something like this (pseudo-code):
React.render(<Component initialState={...} />);
I know I could use a prop to work as the initial state but this smells like an anti-pattern.
What should I do?
EDIT FOR CLARITY
Imagine I have a CommentList component. By the time I first render it, the initial state corresponds to the snapshot of current comments from my database. As the user includes comments, this list will change, and that's why it should be a state and not props. Now, in order to render the initial snapshot of comments I should pass it to the CommentsList component, because it has no way to know it. My confusion is that the only way I see to pass this information is through a props which seems to be an anti-pattern.
Disclaimer: Newer versions of React handle this on a different way.
Only permanent components might be able to use props in the getInitialState. Props in getInitialState is an anti-pattern if synchronization is your goal. getInitialState is only called when the component is first created so it may raise some bugs because the source of truth is not unique. Check this answer.
Quoting documentation:
Using props, passed down from parent, to generate state in
getInitialState often leads to duplication of "source of truth", i.e.
where the real data is. Whenever possible, compute values on-the-fly
to ensure that they don't get out of sync later on and cause
maintenance trouble
You can still do:
getInitialState: function() {
return {foo: this.props.foo}
}
As they will be the default props for your app. But as long as you are using a prop to set a value that presumably won't change, you can use the same prop inside of the render function.
<span>{this.props.foo}</span>
This props won't be modified, so no problem using it each time the render is called.
Edited answer:
In this case your initial state should not be a prop, should be an ajax call which populates the comment list.
To quote the React docs:
Using props, passed down from parent, to generate state in getInitialState often leads to duplication of "source of truth", i.e. where the real data is. Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble
And:
However, it's not an anti-pattern if you make it clear that synchronization's not the goal here
So if your props include a value and an initialValue, then it's clear that the latter is for initialization, and there's no confusion.
See the React docs for code examples.
If you know the state then I would tend to argue that the component you are rendering is not really in control of it. The idea in React is that any particular piece of state lives in only a single location.
After seeing the other answers, and studying a little bit about it, I've come to this conclusion:
If you are rendering React in the client (compiled or not), which is the default approach, you should try to make an extra Ajax call from inside your component to get the initial state. That is, don't use props. It's cleaner and less error prone.
However, if you are rendering in the server (Node.js or ReactJs.NET), there's no reason to make this extra Ajax call for each request.. Besides, it's not SEO friendly. You want the complete page to come as the result of your request (including data). So, as #RandyMorris pointed out, in this case it's ok to use props as the initial state, as long as it's exclusively the initial state. That is, no synchronization.

Categories

Resources