I am following React & Redux. I have actions, reducers working separately. I am managing state more or less properly.
I am trying to create a ui which is having few textboxes and a button(disabled). In text boxes i had added onchange event on which it call a function
onChangeTextbox(){
}
In this function I do the following thing.
1. I update the state of the redux store.
onChangeTextbox(){
updateStateOfTextBox();
}
2.After doing this I look for whether all the text boxes, in the ui, is having something in it. If so I will enable my button to do further operations.
onChangeTextbox(){
updateStateOfTextBox();
updateStateOfButton();
}
Everything is working good except the one thing.
That one thing is as soon as I give the last empty textbox one character, the button is not enabled immediately, and when I give more character the button gets enabled. Similarly vice versa for disabling button.
The problem which I found is that when control complete its job of function updateStateOfTextBox(); and enters the updateStateOfButton(); function the state remains same. And again when render() occurs the change in state is reflected then.
I want to fix that issue and I am not getting any way out. Any solution and suggestion to this will be appreciated.
Thanks.
I found the solution to such situation.
componentsWillRecieveProps(newProps){
}
this method of the life cycle changes the game.
componentsWillRecieveProps(newProps){
newProps.state // this will give you new updated state which your action updated.
this.props.state // this will give you local or your state
// Here you can update your local state with global state
// And call the other function here as
updateStateOfButton();
}
Therefore the solution can be interpreted like
onChangeTextbox(){
updateStateOfTextBox();
}
componentsWillRecieveProps(newProps){
.
.
updateStateOfButton();
}
Related
I am trying to hide an element 'GorillaSurfIn' after I click on it.
But also it should fire the 'setShouldGorillaSurfOut' to 'true'. The second part works, but after I added this function:
function hideGorillaSurfIn() {
let element = document.getElementById('gorilla-surf-in');
ReactDOM.findDOMNode(element).style.display =
this.state.isClicked ? 'grid' : 'none';
}
After I click, the code falls apart.
Once I click, the element should be hidden/removed till the next time the App restarts.
Here is the Code Sandbox Link for further explanation.
I am open to any solutions, but also explanations please, as I am still fresh in learning React.
I have changed your code a bit to make it work. You can make further changes according to your need. A few things that I would like to add: -
You should avoid using findDOMNode (in most cases refs can solve your problem) as there are certain drawbacks associated with findDOMNode, such as the react's documentation states "findDOMNode cannot be used with functional components".
I've used refs (forward ref in this case) to make it work.
GorillaSurfIn was called twice, so there were two Gorilla gifs on the screen with same IDs. Not sure if that was the intended behaviour but each element should have unique ID.
Check out the code sandbox.
This is my profile settings page: Code
My buttons already call onClick function, but i wanna add saveInfo to my "save" button.
I just noticed that after clicking "save" the only field that remains saved is First Name, can you explain to me why?
I adjusted your code for this to work properly.
Here is an updated sandbox https://codesandbox.io/s/charming-kapitsa-kznoi?file=/src/UserInfo.js
I extracted all of your additional code so it would be easier for me to debug, which is why you won't see some of the code in your original example.
Quite simply, the issue was that you were rendering an empty <input> when saved was not true.
If you want to send your saveInfo simply set the value of each input (when saved isn't true) to the value of your saveInfo.
I left comments within to help understand.
With react-color https://casesandberg.github.io/react-color/ .
I can use ready-made onChangeComplete function from react-color.
But I wonder how can I create that onChangeComplete by using input type color tag.
I tried onBlur but the color won't change until user clicks or presses tab
On the other hand, using onChange keep firing updates.
Because currently I'm using redux state, so dispatching update continuously when I drag and choose color isn't a good way.
Any ideas how to create onChangeComplete?
It depends on how you'd like to define a change. To prevent continuous updates every time the mouse moves, you'll probably want to update Redux state only when the mouse stops moving. (This seems to be the behaviour on the page you linked to).
You could use the following JavaScript to detect when the mouse stops moving:
let timer;
window.addEventListener('mousemove', function (e) {
console.log('Mouse moving');
clearTimeout(timer);
timer = setTimeout(() => console.log('Mouse stopped'), 300);
});
Then, try putting the above code inside your ComponentDidMount() method and replace console.log('Mouse stopped') with whatever Redux action you want to dispatch!
300 is the number of milliseconds without movement that will trigger the action, which could be changed depending on how sensitive you want your app to feel.
Lastly, remember to remove the event listener in your ComponentWillUnmount() method.
https://github.com/casesandberg/react-color/blob/7ee60d845e5d5e11e4f6ecb895b2d9755c59d09d/src/components/common/ColorWrap.js#L30
Here is the code that how react-color implemented onChangeComplete.
It is hard coded using debounce.
I put the link there for anyone interested in using that solution
I come from the Ember world so apologies if this question is very basic (I'm sure it is). I have a component which sets the state "scrollPosition" whenever the window is scrolled. I would like to define a new state property, "isScrolledToTop", which is equal to true when "scrollPosition" is 0.
In Ember I would have simple defined a new property and checked the condition when scrollPosition changed. Not quite sure how to do this in React. I was thinking of using "componentDidUpdate", but pretty sure this is not the right approach. Thanks for the help in advance!
If you're asking "how can I fire some event once the user scrolls to the top of the page" then the answer is to do that in the onscroll event callback.
If you want to render something differently (e.g. a full-size header) when the scroll position is at the top of the page, then the logic would go in the render() method of your component. Something like:
render() {
if (this.state.scrollPosition === 0) {
// do something specific to this scenario
}
return ...
}
This part of the docs suggests not putting 'computed data' in state, which is what isScrolledToTop is.
As an FYI, if you're tracking the scroll position, the window object keeps this in its 'state' for you, available at window.scrollY - you don't need to duplicate this into your component's state.
I'm running into a weird case that only seems to happen upon first loading a component on a heavily based component page (loading 30+ components).
#Component{
selector: <parent-component>
template: `<child-component [myObject]=myObject>
}
export class ParentComponent {
private myObject:DTOValue;
constructor(service:MyService){
service.getDTOValue().subscribe((dtoValue:DTOValue) => {
this.myObject = dtoValue;
});
}
}
#Component{
selector: <child-component>
template: `<div></div>
}
export class ChildComponent {
#Input set myObject(value:DTOValue) => {//do something};
constructor(){
}
}
In this code, the Parent is going to get a value to a child as an input. This value comes from a request at a later time, so when the child is first initialized, the input could be undefined. When the value does get returned from the request and is set on the variable myObject, I'd expect that the child component would receive an input event being triggered. However, due to the timing, it seems like this is not always the case, especially when I first load a page that contains a lot of files being loaded.
In the case that the child component doesn't receive the input, if I click else where on my page, it seems to now trigger the change detection and will get the input value.
The 2 possible solutions I can think of that would require some large code changes so I want to make sure I choose the right now before implement them.
Change the input to be an Subject, so that I push the input value which should ensure that a correct event is triggered(this seems like overkill).
Use the dynamic loader to load the component when the request as return with the correct value (also seems like overkill).
UPDATE:
Adding a plnker: http://plnkr.co/edit/1bUelmPFjwPDjUBDC4vb, you can see in here that the title seems to never get its data bindings applied.
Any suggestions would be appreciated.
Thanks!
If you can identify where the problem is and appropriate lifecycle hook where you could solve it, you can let Angular know using ChangeDetectorRef.
constructor(private _ref: ChangeDetectorRef)
method_where_changes_are_overlooked() {
do_something();
// tell angular to force change detection
this._ref.markForCheck();
}
I had a similar issue, only with router - it needed to do redirect when/if API server goes offline. I solved it by marking routerOnActivate() for check...
When you trigger change detection this way a "branch" of a component tree is marked for change detection, from this component to the app root. You can watch this talk by Victor Savkin about this subject...
Apologize, the issue ended up being my interaction with jQuery. When I triggered an event for a component to be loaded, inside of the jQuery code, it wouldn't trigger the life cycle. The fix was after the code was loaded to then call for a change detection.