How to listen state changes in react.js?
I haven't used Angular, but reading the link above, it seems that you're trying to code for something that you don't need to handle. You make changes to state in your React component hierarchy (via this.setState()) and React will cause your component to be re-rendered (effectively 'listening' for changes).
If you want to 'listen' from another component in your hierarchy then you have two options:
- Pass handlers down (via props) from a common parent and have them update the parent's state, causing the hierarchy below the parent to be re-rendered.
- Alternatively, to avoid an explosion of handlers cascading down the hierarchy, you should look at the flux pattern, which moves your state into data stores and allows components to watch them for changes. The Fluxxor plugin is very useful for managing this.
React js update child state from an event in the parent
You need to assign a new value to the state variable. Please try this
this.setState(state => ({ data: [...state.data, result.c.gas] }))
In your case you were mutating its value
Updating Multiple React State within the same event handler
setState is asynchronous
, it means that when it is called, its state won't update at the same time, it takes some time to perform its action.
You can make use of useEffect
to do that.
useEffect
will perform an action only when the specified state (inside brackets) changes
useEffect(() => {
setLocation({
...location,
location: locationAddress,
locationID: uuidv4()
})
}, [locationAddress]) //When locationAddress changes, setLocation
useEffect(() => {
setLocationList([
...locationList,
location.locationID
])
}, [location]) //When location changes, insert Id
Ps: You can have multiple useEffects in your code.
Updating state on props change in React Form
componentWillReceiveProps is depcricated since react 16: use getDerivedStateFromProps instead
If I understand correctly, you have a parent component that is passing start_time
down to the ModalBody
component which assigns it to its own state? And you want to update that time from the parent, not a child component.
React has some tips on dealing with this scenario. (Note, this is an old article that has since been removed from the web. Here's a link to the current doc on component props).
Using props to generate state in
getInitialState
often leads to duplication of "source of truth", i.e. where the real data is. This is becausegetInitialState
is only invoked when the component is first created.Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.
Basically, whenever you assign parent's props
to a child's state
the render method isn't always called on prop update. You have to invoke it manually, using the componentWillReceiveProps
method.
componentWillReceiveProps(nextProps) {
// You don't have to do this check first, but it can help prevent an unneeded render
if (nextProps.startTime !== this.state.startTime) {
this.setState({ startTime: nextProps.startTime });
}
}
What is the best way to trigger onchange event in react js
For React 16 and React >=15.6
Setter .value=
is not working as we wanted because React library overrides input value setter but we can call the function directly on the input
as context.
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, 'react 16 value');
var ev2 = new Event('input', { bubbles: true});
input.dispatchEvent(ev2);
For textarea element you should use prototype
of HTMLTextAreaElement
class.
New codepen example.
All credits to this contributor and his solution
Outdated answer only for React <=15.5
With react-dom ^15.6.0
you can use simulated
flag on the event object for the event to pass through
var ev = new Event('input', { bubbles: true});
ev.simulated = true;
element.value = 'Something new';
element.dispatchEvent(ev);
I made a codepen with an example
To understand why new flag is needed I found this comment very helpful:
The input logic in React now dedupe's change events so they don't fire
more than once per value. It listens for both browser onChange/onInput
events as well as sets on the DOM node value prop (when you update the
value via javascript). This has the side effect of meaning that if you
update the input's value manually input.value = 'foo' then dispatch a
ChangeEvent with { target: input } React will register both the set
and the event, see it's value is still `'foo', consider it a duplicate
event and swallow it.This works fine in normal cases because a "real" browser initiated
event doesn't trigger sets on the element.value. You can bail out of
this logic secretly by tagging the event you trigger with a simulated
flag and react will always fire the event.
https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128
OnChange event using React JS for drop down
The change event is triggered on the <select>
element, not the <option>
element. However, that's not the only problem. The way you defined the change
function won't cause a rerender of the component. It seems like you might not have fully grasped the concept of React yet, so maybe "Thinking in React" helps.
You have to store the selected value as state and update the state when the value changes. Updating the state will trigger a rerender of the component.
var MySelect = React.createClass({
getInitialState: function() {
return {
value: 'select'
}
},
change: function(event){
this.setState({value: event.target.value});
},
render: function(){
return(
<div>
<select id="lang" onChange={this.change} value={this.state.value}>
<option value="select">Select</option>
<option value="Java">Java</option>
<option value="C++">C++</option>
</select>
<p></p>
<p>{this.state.value}</p>
</div>
);
}
});
React.render(<MySelect />, document.body);
Also note that <p>
elements don't have a value
attribute. React/JSX simply replicates the well-known HTML syntax, it doesn't introduce custom attributes (with the exception of key
and ref
). If you want the selected value to be the content of the <p>
element then simply put inside of it, like you would do with any static content.
Learn more about event handling, state and form controls:
- http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html
- http://facebook.github.io/react/docs/forms.html
setState doesn't work within an event handler
You should get the updated state inside the callback provided as second argument in setState
, like this
class DropDownItem extends Component {
constructor(props) {
super(props)
this.state = {
selectedItem : ""
}
this.updateItem = this.updateItem.bind(this)
}
updateItem (item, callback) {
this.setState({selectedItem : item}, callback)
}
render(){
return (
<div>
<DropdownItem onClick={() => {
this.updateItem(this.props.product, ()=>{
console.log("item",this.state.selectedItem)
})
}}
>{this.props.product}</DropdownItem>
<DropdownItem divider/>
</div>
)
}
}
Related Topics
Why Are Certain CSS Properties Not Applied to A:Visited
Is There Any Clean CSS Method to Make Each Letter in a Word a Different Color
Less CSS Set Variables in Media Query
Change Parent Div on Input[Type=Checkbox]:Checked with CSS
Fonts Are Not Rendered Correctly in Release Mode, But Is Working on Debug Mode in Asp Net Webforms
Small Margin/Gap at the Top of Document
CSS Variables Defaults: Set If Not Already Set
:Last-Child Pseudo-Class Mixed with Attribute Selector Not Working
Grid Styling - Overwrite Style of Ag-Grid
Disable CSS Animation on Pseudo Element Inherited from Parent
Rotating a Text to 270 Degrees in IE8
CSS - Font Being Blocked from Cross-Origin Resource Sharing Policy
CSS Min-Height Not Working on Mozilla Firefox
Background Color of Tspan Element
Selector for Nth Nested Elements