React change state of checkbox - reactjs

Class component - list of items with a boolean property ; I've added onChange method to change state of this propery in a collection. When I try to compile I have:
Line 15:59: Array.prototype.map() expects a return value from arrow
function array-callback-return
import React from "react";
class ItemList extends React.Component {
constructor(props) {
super(props);
this.state = {
items: props.items
}
}
toggleCompleted = (position) => {
const updatedItems = this.state.items.map((item, idx) => {
position === idx ? {...item, completed: !item.completed} : item //err
})
this.setState({
items: updatedItems
})
}
render() {
return(
<div className="col-12 col-lg-8 mx-auto">
<h3 className="h3">Tasks</h3>
{this.state.items.length > 0 &&
<table className="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Description</th>
<th scope="col">Completed</th>
</tr>
</thead>
<tbody>
{this.state.items.map((item, idx) => {
return (
<tr key={idx+1}>
<th scope="row">{idx+1}</th>
<td>{item.title}</td>
<td>{item.description}</td>
<td>
<input
id={"completed".concat(idx)}
className="form-check-input"
type="checkbox"
checked={item.completed}
onChange={() => {this.toggleCompleted(idx)}}/>
</td>
</tr>
);
})}
</tbody>
</table>
}
</div>
)
}
}
export default ItemList;
Why?

Add missing return statement:
const updatedItems = this.state.items.map((item, idx) => {
return position === idx ? {...item, completed: !item.completed} : item
})
or remove {}
const updatedItems = this.state.items.map((item, idx) =>
position === idx ? {...item, completed: !item.completed} : item
)
Read more about basics here

Add a "return" before
position === idx ? {...item, completed: !item.completed} : item

Related

I have a react table im trying to get it to sort when I click on the this different table Heads

I would assume the issue is coming from signaling portion of the code and the format I have set it in but from all accounts, this should work I know I can break it into an if-else statement but this is the absolute first thing I have created in React and I am trying to use this format. I provided the whole code for the table but the rest is working properly it's just the sorting I am trying to get to work any tips or suggestions would be greatly appreciated. Also if there is anything else in the code you see that I could improve upon as well am open to all suggestions to learn and improve, my search filter is having issues as well but I'm hoping to resolve that.
enter class AppTable extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
sorted: '',
directory: 'asc',
compile: [],
};
}
componentDidMount() {
axios.get(`https://randomuser.me/api/?results=20&nat=us`)
.then(res => {
let users = (res && res.data) ? res.data.results: [];
if (!users || users.length === 0){
this.setState({loading: false});
return;
}
const tableList = users.map(state => new User(state));
this.setState({ compile: tableList, users: tableList });
})
}
sorting(sorted) {
const currentField = this.state.sorted;
const users = this.state.users;
let directory = this.state.directory;
if (currentField === sorted) {
directory = directory === 'asc' ? 'desc' : 'asc'
}else{
directory = 'asc'
}
this.signaling(users, sorted,directory);
this.setState({users: users, directory: directory, sorted: sorted})
}
**signaling(objects, field, direction){
const signal = direction === "asc" ? 1 : -1
objects.sort((a,b) => (a[field] > b[field]) ? signal * 1 : ((b[field] > a[field]) ? signal * -1 : 0));
}**
initSearch(evt) {
const searchValue = evt.target.value;
const compile = this.state.compile;
if (!searchValue){
this.setState({users: compile});
return;
}
const filtering = compile.filter((object)=>{
return Object.keys(object).reduce((acc, curr)=>{
return acc || object[curr].toLowerCase().includes(searchValue);
}, false);
});
this.setState({users: filtering});
}
render() {
const throughput = this.state.users;
return <Col>
<Form inline className="mb-2">
<Form.Label className="my-1 mr-2">Search:</Form.Label>
<Form.Control type="text" onChange={event => this.initSearch(event)} placeholder="Search Table" />
</Form>
<Table striped bordered hover>
<thead>
<tr>
<th className="pointer" onClick={() => this.sorting(`${this.firstName}`)}>First Name</th>
<th className="pointer" onClick={() => this.sorting(`${this.lastName}`)}>Last Name</th>
<th className="pointer" onClick={() => this.sorting(`${this.email}`)}>Email</th>
<th className="pointer" onClick={() => this.sorting(`${this.street}`)}>Street</th>
<th className="pointer" onClick={() => this.sorting(`${this.city}`)}>City</th>
<th className="pointer" onClick={() => this.sorting(`${this.state}`)}>State</th>
<th className="pointer" onClick={() => this.sorting(`${this.phone}`)}>Phone</th>
</tr>
</thead>
<tbody>
{throughput.map((individual, index) => (
<AppRow key={index} user={individual}/>
))}
</tbody>
</Table>
</Col>;
}
}
export default AppTable;

HTML table juggle back when checking or selecting a row after sorting a column

The grid before sorting is as follows:
Now I am going to sort it with Patient ID
Now when I check the Patient ID: 936447 which is in last position after sorting the grid returns to it's original ordering.
But I want the sorted grid even after checking the checkbox/ selecting a row.
This the code for displaying the grid and sorting the grid.
class App extends Component {
constructor(props) {
super(props);
this.state = {
order: {},
orderby: '',
printQueueList: props.printQueueList && props.printQueueList,
};
this.sort = this.sort.bind(this);
}
componentWillReceiveProps(nextProps) {
if (this.state.printQueueList != nextProps.printQueueList)
this.setState({ printQueueList: nextProps.printQueueList && nextProps.printQueueList });
}
sort(event) {
const { order } = this.state;
let { printQueueList } = this.props;
var gridData = printQueueList;
order[event.target.id] = !order[event.target.id];
gridData = _.orderBy(gridData, (o) => typeof o[event.target.id] === 'string' ? o[event.target.id].trim().toLowerCase() : o[event.target.id], order[event.target.id] ? 'asc' : 'desc');
this.setState({
orderby: event.target.id,
printQueueList: gridData,
order
});
}
render() {
return (
<div className="App">
<table >
<thead >
<tr >
<th id="select" >
<Checkbox
input={{
name: 'selectAll',
onChange: //function
value: allSelected
}}
/>
<label htmlFor="SelectAll" >Select All</label>
</th>
<th id="PatientID" onClick={this.sort}>Patient ID {order.PatientID ? <i id="PatientID" className="fa fa-sort-asc" /> : <i id="PatientID" className="fa fa-sort-desc" />}</th>
<th id="DocType" onClick={this.sort}>Type {order.DocType ? <i id="DocType" className="fa fa-sort-asc" /> : <i id="DocType" className="fa fa-sort-desc" />}</th>
</tr>
</thead>
<tbody >
printQueueList && printQueueList.map((Queue, i) => {
return (
<tr key={Queue.PrintQueueID}
onClick={() => onSelectPrintQueueGrid(Queue.PrintQueueID)}>
<td >
<Checkbox
input={{
name: Queue.PrintQueueID,
onChange: //function
value: selectedPrintQueueList.indexOf(Queue.PrintQueueID) !== -1,
}}
/>
</td>
<td className="dashboard_table-cell" title={'Patient ID:' + Queue.PatientID}>{Queue.PatientID}</td>
<td className="dashboard_table-cell" title={'Type:' + Queue.DocType}>{Queue.DocType}></td>
</tr>)
}
)
</tbody>
</table>
</div>
)
}
}
const mapStateToProps = state => {
return {
printQueueList: state.myDashboardReducer.printQueueList,
};
};
const mapDispatchToProps = dispatch => {
return {
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);
Since componentWillReceiveProps(nextProps) updates the state with the newProps, the array printQueueList gets updated. For that reason before updating with newProps, I checked whether the array is sorted or not.
If it isn't sorted, update printQueueList with newProps.
componentWillReceiveProps(nextProps) {
if(_.isEmpty(this.state.order)){
if (this.state.printQueueList != nextProps.printQueueList)
this.setState({ printQueueList: nextProps.printQueueList && nextProps.printQueueList });
}
}

React collapse row onClick

I have data that I need to show in table, for all rows I would like to use collapse function. Now I have working code that is collapsing all rows on click, but in what way I can collapse only one already clicked?
This is my code:
class Data extends React.Component {
constructor(props) {
super(props);
this.state = {
datas: [
{name: "or1", status: 11},
{name: "or3", status: 2},
{name: "or2", status: 22},
],
expanded: [],
isOpen: true,
};
}
toogleContent(openIs) {
this.setState({
isOpen: !openIs
})
}
render() {
return (
<Table responsive>
<thead className="text-primary">
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{this.state.datas.map((data, i) => (
<tr id={i} onClick={this.toogleContent.bind(this, this.state.isOpen)}>
<td>{data.name}</td>
<td><Collapse isOpen={this.state.isOpen}>
{data.status}</Collapse>
</td>
</tr>
))}
</tbody>
</Table>
)
}
}
I used their indexes to find out if they are opened or not, but you can use their names too, or add at data object a key isOpened =>
state={
isOpenIndexes = []
}
toogleContent(index) {
// we check if already opened
this.state.isOpenIndexes.find(openedIndex => openedIndex ===index ) ?
this.setState({
isOpenIndexes: this.state.isOpenIndexes.filter(openedIndex => openedIndex!==index)
})
:
this.setState({
isOpenIndexes: isOpenIndexes.concat([index])
})
}
{datas.map((data, i) => (
<tr id={i} onClick={this.toogleContent.bind(this, i)} isOpened={this.state.isOpenIndexes.find(openedIndex => openedIndex ===i )}>
<td>{data.name}</td>
<td>{data.status}</td>
</tr>
))}

How to handle a onClick method in a component?

I believe I have my props setup correctly, but I keep getting "Cannot read property 'props' of undefined"
Child component:
const SearchResults = props => (
<div>
<div className="row" ><h4 style={{margin:"auto", marginBottom:"15px"}}>Search Results:</h4></div>
<table className="table table-striped">
<thead>
<tr>
{props.labels.map(label => ( <th key={label.Id}>{label.DisplayName}</th>))}
</tr>
</thead>
<tbody>
{ props.contracts.map((contract, i) => <tr key={i} data-id={contract.Id} onClick={() => this.props.handleContract(contract.Fields.filter(field => field.DataField==="IDXT001").map(field => field.DataValue))} className="clickable-row">{contract.Fields.map( docs => <td key={docs.Id}><span id={docs.DataField}>{docs.DataValue}</span></td>)}</tr> )}
</tbody>
</table>
</div>
)
Parent:
class SearchPage extends React.Component {
constructor(props) {
super(props);
this.state = {
labels: [],
contracts: [],
formValues:"",
pdfs:[],
id:"",
};
}
<SearchResults
labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs}
handleContract={this.onClick}
/>
You need to change this.props.handleContract to props.handleContract. this doesn't exist in your functional component.
const SearchResults = props => (
<div>
<div className="row" ><h4 style={{ margin: "auto", marginBottom: "15px" }}>Search Results:</h4></div>
<table className="table table-striped">
<thead>
<tr>
{props.labels.map(label => (<th key={label.Id}>{label.DisplayName}</th>))}
</tr>
</thead>
<tbody>
{props.contracts.map((contract, i) => <tr key={i} data-id={contract.Id} onClick={() => props.handleContract(contract.Fields.filter(field => field.DataField === "IDXT001").map(field => field.DataValue))} className="clickable-row">{contract.Fields.map(docs => <td key={docs.Id}><span id={docs.DataField}>{docs.DataValue}</span></td>)}</tr>)}
</tbody>
</table>
</div>
);
On your parent, make sure you have bound the onClick function as mentioned in the comments.
class SearchPage extends React.Component {
constructor(props) {
super(props);
this.state = {
labels: [],
contracts: [],
formValues: "",
pdfs: [],
id: ""
};
}
onClick = () => {
// Bind the function like this.
}
render() {
return (
<SearchResults
labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs}
handleContract={this.onClick}
/>
);
}
}

How to pending button show approved on click event by reactjs

When I click the "pending" button, the status does not change with this code, and shows the message
TypeError: this.state.data.map is not a function
Please help me!
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{
id: 1,
name: "farid",
age: 15,
status: "pending"
},
{
id: 2,
name: "kamal",
age: 15,
status: "pending"
}
],
}
}
movementappTDClick = (id) => () => {
const index = this.state.data.findIndex((data) => {
return data.id === id
})
let data = Object.assign({}, this.state.data[index]);
console.log('data is', data);
data.status = "approved"
console.log("sec data is", data);
this.setState({ data });
};
render() {
return (
<div className="App">
<Card>
<CardBody>
<Table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
{this.state.data && this.state.data.map(movement => (
<tr key={movement.id}>
<th>{movement.id}</th>
<td>{movement.name}</td>
<td>{movement.age} </td>
<td>
<button
onClick={this.movementappTDClick(movement.id)}
>
{movement.status}
</button>
</td>
</tr>
))}
</tbody>
</Table>
</CardBody>
</Card>
</div>
);
}
}
try to modify your movementappTDClick function.
movementappTDClick = index => {
const data = [...this.state.data];
const row = data[index];
row.status = "approved";
data.splice(index, 1, row);
this.setState({ data });
};
render() {
return (
<div className="App">
<Card>
<CardBody>
<Table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
{this.state.data &&
this.state.data.map((movement, index) => (
<tr key={movement.id}>
<th>{movement.id}</th>
<td>{movement.name}</td>
<td>{movement.age} </td>
<td>
<button onClick={() => this.movementappTDClick(index)}>
{movement.status}
</button>
</td>
</tr>
))}
</tbody>
</Table>
</CardBody>
</Card>
</div>
);
}
}
I modified your code. Please check this.
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{
id: 1,
name: "farid",
age: 15,
status: "pending"
},
{
id: 2,
name: "kamal",
age: 15,
status: "pending"
}
],
}
}
movementappTDClick = (index) => () => {
const { data } = this.state;
data[index] = {
...data[index],
status: 'approved'
}
this.setState({ data }); };
render() {
const { data } = this.state;
return (
<div className="App">
<Card>
<CardBody>
<Table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
{data && _.map((data || []), (movement, index) => (
<tr key={movement.id}>
<th>{movement.id}</th>
<td>{movement.name}</td>
<td>{movement.age} </td>
<td>
<button
onClick={this.movementappTDClick(index)}
>
{movement.status}
</button>
</td>
</tr>
))}
</tbody>
</Table>
</CardBody>
</Card>
</div>
);
}
}

Resources