React.js get checked inputs - reactjs

I am quiet new to React and I wasn't able to figure out how to manipulate DOM.
I have a set of components with checkboxes, and I have a delete button, I want to delete the checked elements when delete button is clicked.
here is a snippet of code I am using :
...
deleteMessage: function(event) {
this.refs.select_message.getDOMNode(); // I get only the last element
},
...
...
render: function() {
var Messages = this.props.messages;
return (
<div>
<button onClick={this.deleteMessage}>Delete</button>
{Messages.map(function(message) {
return (
<div>
<input type='checkbox' className='select_message' ref='select_message'/>
</div>
);
})}
</div>
);
Am I doing it the right way?

What you should do is, in your deleteMessage, call a handler which you have passed from the parent. That, in turn, modifies the messages array from the outside. Then the new messages array will be passed in as props. The main insight you need is props are not only data passed for rendering, but also functions to be called when user interaction happens inside the component.

Related

Save information on div and retrieve that information onClick Event

Let's say that i have an array of 5 integers
[1,2,3,4,5]
I iterate the array and i create 5 divs. On each div i want to have a onClick handler. So when i click on a div i want to retrieve the number.
What is the best way to store the info, so later i can retrive it from the handler function?
I have tried the following and it's working, but i am not sure if this is the best solution because in my app i will have a large amount of these divs.
const array = [1,2,3,4,5];
// make a closure
function onDivClick(id) {
return () => {
console.log(id);
}
}
return (
<div>
{array.map( id => {
return <div onClick={onDivClick(id)}> ... </div>
})
</div>
)
I have seen also the the html data attribute:
So i can store and i can retrive it after with event.target.getAttributes('data-id').
Is there other ways, and which is the best?
What you have right now is not okay. {onDivClick(id)} executes on every render.
Instead, add the id attribute directly to the div, and access it in the click handler.
Rewrite your click handler like so:
function handleClick(event) {
let id = event.target.id;
console.log(id);
}
and attach it to the div like so:
<div id={id} onClick={handleClick} />

How do I make children's props update when parent state changes for children initialized in a map function?

I have a bunch of child components being initialized in a map function in ComponentDidMount:
this.mappedApplications = this.props.applications.map((application, key) =>
<ApplicationCard
selectedYear={this.state.openApplicationYear}
applicationYear={application.application_year}
handleArrowClick={this.handleApplicationCardArrowClick}
key={key}
/>, this
);
this.setState({
applications: this.mappedApplications,
});
When the state.openApplicationYear changes I want it to change for all of the Application Cards. I do a check in the application card show info if the selected year matches the application year, with the goal that only one card will be open at a time. The cards have dropdown arrows that allow the user to open or close them. Right now the parent's openApplicationYear is changing correctly, but the children's aren't updating.
Here is the render function if it helps:
render() {
return (
<div className="dashboard__card">
<h3 className="mb-3">Applications</h3>
{this.state.applications}
</div>
)
}
I have bound "this" to the map function as seen above. Is there anything else I need to do to update the children when the parent's state changes?

Change dynamically name of the tab from field

so i have 3 react component 1 is the whole dialog component, tabs component and tabsContent component.And for example in tab content i have a field that when you write something it change the tab name on what you write.. I have done that with .forceUpdate everytime when you change that field it call function from dialog component and their it have .forceUpdate.. and that field is bind with the same object like the tab name. The problem is that if i have for example like 10 fields whenever i change a field it will call that forceUpdate and i don't need to call it everytime only for 1 field.So can you give me some way to do it that ?
window.DialogComponent = react.createClass(
componentDidMount(){
this.props.obj...;
}
onChange:function(){
this.forceUpdate()
}
render:function(){
return(
<dialogTab obj={this.props.obj} />
<dialogContent obj={this.props.obj} onChange={this.onChange} />
)
}
)
dialogTabComponent =react.createClass(
render:function(){
return(
<span>this.props.obj.name</span>
)
}
)
dialogTabContent = react.createClass(
onChange(){
this.props.obj.name = value;
this.props.onChange();
}
render:function(){
return(
<input text.... onChange = {this.onChange}>
)
}
)
If I understood it right, you have a DialogComponent that contains two child components (DialogTab and DialogContent).
DialogContent contains an input that, whenever is changed, will update some value on its sibling component, DialogTab. So basically you have a need for communication between sibiling components.
You should make use of the state in your parent component and pass props from your parent (DialogComponent) to its children, here is a fiddle: https://jsfiddle.net/69z2wepo/62767/
Good luck.

React rerender only one child

in my form i have a few dropdown components. Whenever first dropdown option changes i want to update props for the second dropdown and rerender it. My code looks like this
handleProjectChange(option) {
//this.setState({ selectedProject: option })
this.refs.phase.props = option.phases;
//this.refs.forceUpdate()
this.refs.phase.render()
}
render() {
var projectOptions = this.projectOptions
var defaultProjectOption = this.state.selectedProject
var phaseOptions = defaultProjectOption.phaseOptions
var defaultPhaseOption = phaseOptions[0]
var workTypeOptions = api.workTypes().map(x => { return { value: x, label: x } })
var defaultWorkTypeOption = workTypeOptions[0]
return (
<div>
<Dropdown ref='project' options={projectOptions} value={defaultProjectOption} onChange={this.handleProjectChange.bind(this)} />
<Dropdown ref='phase' options={phaseOptions} value={defaultPhaseOption} />
<Dropdown options={workTypeOptions} value={defaultWorkTypeOption} />
<button className="btn btn-primary" onClick={this.handleAddClick.bind(this)}>Add</button>
</div>
)
}
But props are not changed, so it rerenders the same options. At the moment im just rerendering entire form by setting new state on it. Is there any way to rerender only one child/Dropdown with new props?
The way to do this is to put the selected option in first dropdown selectedProject in state.
And inside your render function, fetch/ populate the options in the second dropdown, dependent on the selected project.
Flow will then be:
User selects an option in the first dropdown.
This triggers handleProjectChange()
Inside handleProjectChange(), the newly selected option is put in state, by a this.setState() call
Because state changed, react re-runs the entire render() function.
Under the hood, react figures out that only the second dropdown has changed, so react will only re-render the second drop-down on your screen/ in the DOM.
Although React does have a reconciliation algorithm that dynamically checks whether each component should be rerenader or not in every rendering of its parent, it doesn't always work as we intended.
https://reactjs.org/docs/reconciliation.html
For this kind of issues, you have two options. You can use either React.pureComponent or React.useMemo().

ReactJS + Flux setState not working on single click

I'm writing my first reactjs + flux application and I have managed to get the basic code working. However, there is a list, which populates another list depending on which list item is clicked. This was working fine until I had my list data hard-coded in the store. But when I started getting the data for the list items from the server, the second list does not get populated on a single click - it needs two clicks to do that. I don't think that getting data from server is a problem because the default data is populated correctly. After debugging, I found out that the store is also returning the data correctly, but the setState() is not setting the data. What am I doing wrong?
Here's my code:
function getInitialData(){
return{
items:DataStore.getFirstItemData()
}
}
var ListItems = React.createClass({
getInitialState:function(){
return getInitialData();
},
_onChange:function(){
this.setState(getInitialData);
},
componentDidMount:function(){
DataStore.addChangeListener(this._onChange);
},
componentWillReceiveProps:function(){
this.setState({items:this.props.itemsData});
},
handleClick:function(e)
{
var data = DataStore.getSubItemsFor(e);
this.setState({items:data});
},
render:function(){
return(
<div>
<div className="col-md-3 dc-left" id="main-list">
<div className="dc-main-list-parent">
{this.props.listData.map(function(list_items){
return(
<div key={list_items.id} onClick = {this.handleClick.bind(this,list_items.id)}>
</div>
);
},this)}
</div>
</div>
<div className="col-md-9 dc-center" id="sub-list">
<SubList sublistData = {this.state.items} />
</div>
</div>
)
}
});
P.S. This code has been modified a little for posting here. Please overlook any syntactical errors - it works!
Probably things break down because updates to the DataStore trigger 2 changes:
The complete component gets rerendered by the parent component, which fires the componentWillReceiveProps + fires a render cycle.
You also have a listener to changes in the DataStore, so the update in the DataStore also fires the _onChange event, which tries to update the state as well
PS: the code has a typo:
this.setState(getInitialData);
should read:
this.setState(getInitialData());
I would suggest you remove the change listener part, and see if that helps..

Resources