the code is here
I want to know that is right? thanks!
Firstly, Please post your code in the question and describe clearly
With getLabels function, you should bind(this) in constructor or use arrow function then you can this.setState in getLabels function.
ex:
constructor(props){
super(props)
this.getLabels = this.getLabels.bind(this)
}
Or:
getLabels = () => {}
You can manage state with react if your application is small, refer here to know how to maintain state in react.
when your applications grows big its difficult to track the state, you may have to go for redux, refer here to know more about redux.
First thing first. "getLabels" functions name is wrong. "setLabels" would be a better name since what you do is assigning the labels to state after retrieving them. So if the rest of the code written correctly it'll trigger a re-render in the component and the UI will be updated with the new state.
if this gets called from a UI button or something, then you'll have to bind to this.
<input type="button" onClick={this.getLabels.bind(this)}/>
Else if it get's called from another function in the same component you can just call it.
function abc(){
this.getLabels()
}
Other than that this is ok for a basic app. But it's better you use some state management pattern like Redux to manage the code and the state.
Related
Say I have a simple component like this one:
export default function Foo({someProp}) {
const a = Math.random();
return <div>{a}{someProp}</div>
}
As far as I know, when someProp updates, React will trigger a re-render. Will it execute the whole Foo function once again and reassign const a a new random value? Will the value be displayed in the <div>?
Thank you.
The answer for every one of your question is yes. A re-render is triggered when there is a props change as you said, and also when there is a state change. When re-rendering and also on the first render, everything behaves like in a normal JavaScript function, as far as assigning variables and everything else, except for some things related to React Hooks, like a state made with useState, a ref made with useRef...
I have working React-Native + Redux registration flow:
Fill inputs
Validate them in component (Formik)
Call action to store registerUser(formData)
Wait for saga to do async call to API
On API error call reducer REGISTER_ERROR what sets store variable formError to some message.
I have my component with mapped state to props (this error message is hooked to prop).
I am doing componentDidUpdate() and when the error prop from store is changed I fire ToastAndroid.show(errorMessage).
But my Toast is called multiple times, because componentDidUpdate is also called multiple times (Redux updating component multiple times).
I know quick workaround by for example creating local state visible and when this state variable is true then no other Toasts are shown.
Is there any better more common way to do it? It is pretty weird in my opinion to rely on Toast's onClose event to set the state variable to false.
As stated in the first answer it'd be good to see the actual code, but what you should be doing is only showing the toast message when the prop changes like this (assuming it's a boolean)
componentDidUpdate(prevProps) {
if(prevProps.showToast === false && this.props.showToast === true){
showToast();
}
}
Without the code, it's a bit hard to try coming up with a solution but I think I know at a high-level what you are trying to do.
If I were you, I would make the presentational component (toast UI in this context) just react to the store props/observables instead of calling the ToastAndroid.show() method directly in the life cycle method.
In terms of architecture pattern, I find this pattern works well with react applications. Hope this helps. https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
I've been trying out React Hooks and they do seem to simplify things like storing state. However, they seem to do a lot of things by magic and I can't find a good article about how they actually work.
The first thing that seems to be magic is how calling a function like useState() causes a re-render of your functional component each time you call the setXXX method it returns?
How does something like useEffect() fake a componentDidMount when functional components don't even have the ability to run code on Mount/Unmount?
How does useContext() actually get access to the context and how does it even know which component is calling it?
And that doesn't even begin to cover all of the 3rd party hooks that are already springing up like useDataLoader which allows you to use the following...
const { data, error, loading, retry } = useDataLoader(getData, id)
How do data, error, loading and retry re-render your component when they change?
Sorry, lots of questions but I guess most of them can be summed up in one question, which is:
How does the function behind the hook actually get access to the functional/stateless component that is calling it so that it can remember things between re-renders and initiate a re-render with new data?
React hook makes use of hidden state of a component, it's stored inside a fiber, a fiber is an entity that corresponds to component instance (in a broader sense, because functional components don't create instances as class components).
It's React renderer that gives a hook the access to respective context, state, etc. and incidentally, it's React renderer that calls component function. So it can associate component instance with hook functions that are called inside of component function.
This snippet explains how it works:
let currentlyRenderedCompInstance;
const compStates = new Map(); // maps component instances to their states
const compInstances = new Map(); // maps component functions to instances
function useState(initialState) {
if (!compStates.has(currentlyRenderedCompInstance))
compStates.set(currentlyRenderedCompInstance, initialState);
return [
compStates.get(currentlyRenderedCompInstance) // state
val => compStates.set(currentlyRenderedCompInstance, val) // state setter
];
}
function render(comp, props) {
const compInstanceToken = Symbol('Renderer token for ' + comp.name);
if (!compInstances.has(comp))
compInstances.set(comp, new Set());
compInstances.get(comp).add(compInstanceToken);
currentlyRenderedCompInstance = compInstanceToken;
return {
instance: compInstanceToken,
children: comp(props)
};
}
Similarly to how useState can access currently rendered component instance token through currentlyRenderedCompInstance, other built-in hooks can do this as well and maintain state for this component instance.
Dan Abramov created a blog post just a couple days ago that covers this:
https://overreacted.io/how-does-setstate-know-what-to-do/
The second half specifically goes into details regarding hooks like useState.
For those interested in a deep dive into some of the implementation details, I have a related answer here: How do react hooks determine the component that they are for?
I would recommend reading https://eliav2.github.io/how-react-hooks-work/
It includes detailed explanations about what is going on when using react hooks and demonstrate it with many interactive examples.
Note - the article does not explain in technical terms how React schedule calls for later phases, but rather demonstrates what are the rules that react uses to schedule calls for later phases.
The URL in another answer given by Eliav Louski is so far the best React explaination I have come across. This page should replace React's official tutorial as it removes all the magic from hooks and friends.
So, I'm trying to learn some react, so far egghead.io is pretty good, but I have a question. I have the following code:
https://jsfiddle.net/42pe/69z2wepo/49393/
Basically these are 3 sliders which update the state on the parent component. Pretty straightforward.
Specifically, I can update the state like this (by passing both val and color):
updateMe(val, color) {
let obj = {};
obj[color] = val;
this.setState(obj);
}
Or I could use the Slider ref to findDOMNode() and then get the value to update the state, but that just didn't feel right. I have no clue what React does in the back, but calling a function from an instance, just so that function can find the instance again to get it's value, when the instance itself could be passing it's value (both value and color prop) all along seems weird.
So, is this a bad practice for some reason?
Both methods are correct but prefer the updateMe . Passing functions in props and child calling that prop function is the ideal way in React.
Refs are ideal where you just want the value and dont want to update state of the react component .For eg , in forms you can use ref to get all the values and make a ajax call to the server.
A better and much cleaner way to do this using ES6 is:
updateMe(val, color) {
this.setState({
[color]: val
});
}
findDOMNode is not a bad practice. But you do not need use it if, you build your application as a function of state and props.
Any change to your state or props should change your DOM and any change to your DOM should be as a result of function of change in state or props.
I have a global data object I update and then I call React.renderComponent() again on the top/main component.
Is this the right pattern for triggering this update?
You should generally pass the data object into the component as a prop, even if it's a global variable. This lets you test the component, and also use it elsewhere without being tied to that global.
As Mike said, there's nothing wrong with using React.renderComponent to update it.
He also mentioned flux, but that's overkill for this. A simple event emitter where you do something like .emit('change', newData), and the component is listening for the change event tends to be better for simpler cases. See my answer to this question for an example of how that can be done.
This is the correct pattern. React.renderComponent will either mount a component for the first time, or get an already mounted component to update.
If you're using a global object though, you might want to look in to the Flux architecture here:
http://facebook.github.io/flux/docs/overview.html
I had the same problem and asked myself if I really needed to re-render the component.
You can do so with this.forceUpdate() but it's not advisable. As React docs states:
You should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.
So what I did was create a data property like exists and test it:
// renderDeleteButton() is being called on render()
renderDeleteButton () {
if (!this.props.store.exists) {
return;
}
return(
<DeleteButton
...
deleteAction={this.delete} />
);
}
Whenever I delete/save, I toggle exists and component will show up or hide based on that. React handles that for me.