How to reload data in a table in React - javascript

I have developed a component which receive data from another component (father). The component who receives the data, the first time, show the data correctly, but the second time, don't do it.
The second time the metho componentWillReceiveProps is called and I have implemented this. But, despite that, the data is not refreshed.
To see the data of this second call, I need to send data to component child a third time and in this moment I will see the data of the second call.
The code of the component child is:
import React, {Component} from "react";
import { Button, Spinner } from "react-bootstrap";
import BootstrapTable from 'react-bootstrap-table-next';
import { columnsTTShootingFEB, sortedTTShootingFEB } from "../../FEBCOM/column.tables";
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
import "../../../css/content.css";
/**
* This constat let me have a row with buttons who show or hide columns
*
* #param {*} param0
*/
const CustomToggleList = ({
columns,
onColumnToggle,
toggles
}) => (
<div className="btn-group btn-group-toggle" data-toggle="buttons" style = {{width: 100 + "%"}}>
{
columns
.map(column => ({
...column,
toggle: toggles[column.dataField]
}))
.map((column, index) => {
if (index > 1){
return (<button
type="button"
key={ column.dataField }
className={ `btn btn-success btn-sm ${column.toggle ? 'active' : ''}` }
data-toggle="button"
aria-pressed={ column.toggle ? 'true' : 'false' }
onClick={ () => onColumnToggle(column.dataField) }
>
{ column.text }
</button>)
}
})
}
</div>
);
class TTShooting extends Component{
constructor(props){
super(props);
this.props = props;
this.state = {
loaded: false
};
}
componentDidMount(){
console.log("Componente cargado");
console.log("id_team_club 1: " + this.props.teams_std_stats[0].id_team_club);
this.setState({
loaded: true,
teams_std_stats: this.props.teams_std_stats
});
}
componentWillReceiveProps(nextProps){
this.props = nextProps;
console.log("id_team_club 2: " + this.props.teams_std_stats[0].id_team_club);
this.setState({
teams_std_stats: this.props.teams_std_stats
});
console.log("Componente recibe nuevos datos");
}
render(){
return(
<div>
{
(this.state.loaded) ?
<div>
{
(this.props.language === "es") ?
<div>
<ToolkitProvider
keyField="id_team_club"
data={ this.state.teams_std_stats }
columns={ columnsTTShootingFEB }
columnToggle
>
{
props => (
<div>
<p className = "text-justify" style = {{fontSize: 12 + "pt"}}><b>Nota: </b>Para añadir o eliminar columnas en la tabla basta hacer clic sobre uno de estos botones</p>
<CustomToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
footerClasses = "footer-class"
defaultSorted = { sortedTTShootingFEB }
/>
</div>
)
}
</ToolkitProvider>
</div>
:
<h2>Pendiente de desarrollo</h2>
}
</div>
:
<div style = {{marginTop: 10 + "px"}}>
<Button variant="dark" disabled>
<Spinner
as="span"
animation="border"
size="sm"
role="status"
aria-hidden="true"
/>
<span className="sr-only">
{(this.props.language === "es") ? "Cargando datos ..." : "Loading data ..."}
</span>
</Button>{' '}
<Button variant="dark" disabled>
<Spinner
as="span"
animation="grow"
size="sm"
role="status"
aria-hidden="true"
/>
{(this.props.language === "es") ? "Cargando datos ..." : "Loading data ..."}
</Button>
</div>
}
</div>
)
}
}
module.exports.TTShooting = TTShooting;
This code returns a log when is called the first time and other times. The first time returns:
> id_team_club 1: 769
This is correct. When I send new data is called the method componentWillReceiveProps, I update the props and the state and show the id_team_club of the firs element and this is the same. The method is called twice.
> id_team_club 2: 769
> Componente recibe nuevos datos
> id_team_club 2
> Componente recibe nuevos datos
But, if I send data again, then I show the data of the second send of data in the second call to the function:
> id_team_club 2: 769
> Componente recibe nuevos datos
> **id_team_club 2: 720**
> Componente recibe nuevos datos
What am I doing wrong? How can I update the data of the table?
Edit
I have updated the code of componentWillReceiveProps and how I pass the data to the table.
componentWillReceiveProps(nextProps){
if (this.props.teams_std_stats !== nextProps.teams_std_stats) {
console.log("Vamos a modificar el state");
this.setState({
teams_std_stats: nextProps.teams_std_stats
});
}
}
<ToolkitProvider
keyField="id_team_club"
data={ this.state.teams_std_stats }
columns={ columnsTTShootingFEB }
columnToggle
>
{
props => (
<div>
<p className = "text-justify" style = {{fontSize: 12 + "pt"}}><b>Nota: </b>Para añadir o eliminar columnas en la tabla basta hacer clic sobre uno de estos botones</p>
<CustomToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
footerClasses = "footer-class"
defaultSorted = { sortedTTShootingFEB }
/>
</div>
)
}
</ToolkitProvider>
But, it doesn't work.

You should not change the props in react, the props of a component are read-only.
This expression is incorrect:
this.props = nextProps;
Please read this article about props props-are-read-only

Do not mutate the props in lifecycle methods. The render function will always have the updated props, you do not need to set this.props.
componentWillReceiveProps(nextProps) {
if (this.props.teams_std_stats !== nextProps.teams_std_stats) {
this.setState({
teams_std_stats: nextProps.teams_std_stats
});
}
}
Also setting this.props = props inside constructor is wrong.
constructor(props){
super(props);
this.state = {
loaded: false
};
}

(Posted a solution on behalf of the question author to move the answer to the answer space).
The problem was due to the data. Because didn't arrive correctly. These data are get it by a query to database after an event and when I assign the id of the element which fire the event this was not assigning correctly to the state.
To assign correctly the value to the state I have to do this:
async handleChange(event){
/**
* If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove
* the synthetic event from the pool and allow references to the event to be retained by user code.
*/
event.persist();
let season = this.state.seasons.find((item) => {
return parseInt(item.id) === parseInt(event.target.value)
});
this.setState({
itemSelected: season.id,
});
}

As others have pointed the problem is related to modifying the props, but I also wanted to add that I see no need to take team_std_stats and to make it part of your component state, you can reference that straight from the props in your render function, why not just do that?
try this line
data={ this.props.teams_std_stats }
instead of
data={ this.state.teams_std_stats }
for your <ToolkitProvider /> implementation.
Hope that helps.

Related

Reload table after deleting an item from it with React

Using React.Js, I created a delete function to delete an item from a table. the delete is working fine but what I want to do is that after deleting I want the tables to be dynamically updated to show only the items left. Now after the delete I have to refresh manually the page or go to another page and comeback to see the items left after the delete
This is the code built so far :
import React, { Component } from "react";
import { Card, Button, Select,/* message, */ Form, Tooltip } from "antd";
import extraitMP3 from "./data";
import { arrayMove, SortableHandle } from "react-sortable-hoc";
import ContainerHeader from "components/ContainerHeader/index";
import { getExtraitMp3, hideMessageUpdate, showUpdateLoader, updateMp3Visibilite } from "appRedux/actions/Comedien";
import { deleteMp3Request } from "../../../appRedux/services/extraitMp3Service"
import { connect } from "react-redux";
import { NotificationContainer, NotificationManager } from "react-notifications";
import { userSignOut } from "appRedux/actions/Auth";
import { displayIcon } from '../../../util/Icon.js';
import CircularProgress from "components/CircularProgress";
import { Modal } from "antd";
const extraitMP32 = [extraitMP3];
const confirm = Modal.confirm;
const Option = Select.Option;
const DragHandle = SortableHandle(() =>
<span className="gx-draggable-icon gx-pt-2">
<i className="icon icon-menu" style={{ fontSize: 25 }} />
</span>);
class ListExtrait extends Component {
onSortEnd = ({ oldIndex, newIndex }) => {
this.setState({
extraitMP3: arrayMove(this.state.extraitMP3, oldIndex, newIndex),
});
};
constructor() {
super();
this.state = {
extraitMP3: extraitMP32[0],
nombreMP3: {
rechercheExtraits: 0,
recherchePossible: 0,
extraitFiche: 0,
extraitFichePossible: '',
extraitArchives: 0,
extraitArchivesPossible: '',
},
loader: false,
}
}
componentDidMount() {
this.props.getExtraitMp3();
}
componentDidUpdate() {
}
static getDerivedStateFromProps(nextProps, prevState,/* nextProps2,prevState2 */) {
if (nextProps.extraitMP3 !== prevState.extraitMP3 && nextProps.extraitMP3) {
return { extraitMP3: nextProps.extraitMP3 };
}
else return null;
}
showDeleteConfirmation(value, id, index, thisHandler) {
confirm({
title: 'Voulez vous supprimer cette audio ?',
content: '',
okText: 'Oui, je confirme',
okType: 'danger',
cancelText: 'Non',
onOk() {
deleteMp3Request(id);
const { extraitMP3 } = thisHandler.state;
Object.keys(extraitMP3).splice(index, 1);
NotificationManager.success("le fichier audio est supprimé avec succès !", "");
},
onCancel() {
},
});
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.showUpdateLoader();
this.props.updateMp3Visibilite(values);
}
});
};
render() {
const { loader, extraitMP3 } = this.state;
const selectOptions = new Map([
[1, "Visible dans la recherche et sur ma fiche"],
[2, "Visible sur ma fiche uniquement"],
[3, "Masqué"],
]);
console.log('extraitMP3', extraitMP3)
function handleChangeSelect(value) {
console.log(`selected ${value}`);
}
return (
<div>
{loader ? <CircularProgress className="gx-loader-400" /> : Object.keys(extraitMP3).map((ids, index) => {
return (
<Card>
<li key={ids}>
<Card styleName="gx-card-list icon icon-data-display gx-mr-2 gx-text-blue gx-fs-xl">
<div className="gx-media-body">
{extraitMP3[ids].Typenom}
{extraitMP3[ids].TypeIcon != null &&
displayIcon(extraitMP3[ids].TypeIcon)
}
</div>
{Object.keys(extraitMP3[ids].TypeMp3List).map(idJson => {
return (
<div className="gx-main-content gx-mb-4">
<ContainerHeader match={this.props.match} />
<div className="gx-contact-item gx-dragndrop-item">
<DragHandle />
<div className="gx-col gx-job-title ">
{extraitMP3[ids].TypeMp3List[idJson].intitule}
</div>
{extraitMP3[ids].TypeMp3List[idJson].interpretation1Icon !== '' &&
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].interpretation1Nom}>
{displayIcon(extraitMP3[ids].TypeMp3List[idJson].interpretation1Icon)}
</Tooltip>
}
{extraitMP3[ids].TypeMp3List[idJson].interpretation2Icon !== '' &&
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].interpretation2Nom}>
{displayIcon(extraitMP3[ids].TypeMp3List[idJson].interpretation2Icon)}
</Tooltip>
}
{extraitMP3[ids].TypeMp3List[idJson].interpretation3Icon !== '' &&
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].interpretation3Nom}>
{displayIcon(extraitMP3[ids].TypeMp3List[idJson].interpretation3Icon)}
</Tooltip>
}
{extraitMP3[ids].TypeMp3List[idJson].langueIcon !== '' &&
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].langueNom}>
<i className={`flag flag-24 gx-mr-2 ${extraitMP3[ids].TypeMp3List[idJson].langueIcon}`} />
</Tooltip>
</div>
}
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<Select
showSearch
style={{ width: '100%' }}
placeholder="Selection la choix de votre numéro de téléphone "
optionFilterProp="children"
onChange={handleChangeSelect}
defaultValue={selectOptions.get(extraitMP3[ids].TypeMp3List[idJson].visibilite)}
filterOption={(input, Option) => Option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
>
{[...selectOptions].map(([value, label]) => <Option value={value}> {label} </Option>)}
</Select>
</div>
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<i className="icon icon-edit gx-fs-xl gx-text-gris" />
</div>
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<span className="gx-pointer">
<i className="icon icon-trash gx-pointer gx-text-danger gx-fs-xxl"
id={extraitMP3[ids].TypeMp3List[idJson].id}
onClick={e => this.showDeleteConfirmation(e.target.value, extraitMP3[ids].TypeMp3List[idJson].id, index, this)} />
</span>
</div>
</div>
</div>
)
})}
<NotificationContainer />
<Button type="primary" htmlType="submit" labelCol={{ xs: 24, sm: 5 }} wrapperCol={{ xs: 24, sm: 12 }}>
Enregistrer
</Button>
</Card>
</li>
</Card>
)
})}</div>
)
}
}
const VisibiliteFormMp3 = Form.create()(ListExtrait);
const mapStateToProps = ({ comedien }) => {
const {
extraitMP3,
alertMessageUpdate,
showMessageUpdate
} = comedien;
return {
extraitMP3,
alertMessageUpdate,
showMessageUpdate
}
};
export default connect(
mapStateToProps,
{
userSignOut,
getExtraitMp3,
hideMessageUpdate,
showUpdateLoader,
updateMp3Visibilite
})(VisibiliteFormMp3);
extraitMP3 is an object of objects that's why I used Object.keys(extraitMP3)
I didn't know how to update the state correctly.
this is the view :
You should put your data in state and then change the state. After changing the state the page automatically re-rendered and changed data of your state will be shown.
So in your delete function simply delete your chosen data and give your remaining data to your state.
Hope this helps, feel free to ask questions if I couldn't explain myself clearly.
I believe you can do this by calling something like and then just call this from within your delete
refreshMp3(){
this.setState({getExtraitMp3: !this.state.getExtraitMp3});}
One of the ideas of React is to make the functionality you ask for simple to implement and it would update automatically. I'm going to abstract a bit from your example. Think about your data in terms of what updates along with the UI. This way we can simplify your component. You have some items that you put in a table. Each item is a row and can be inside an array. We put that array in the state.
class ListExtrait extends Component {
constructor() {
super();
this.state = {
rowsForTable: [...],
somethingElse...
}
...
Then in the JSX in the render method you can render the table rows using map:
rowsForTable.map(item => <div/li/whatever>{item.name or something else}</div>
This way whenever an item is gone from rowsForTable the component will automatically update it's view and the table rows will be up to date.
You can simply call the function while clicking the delete button say deleteHandler. On that function call the api you have made to delete the item and then after successfull delete again call the api that will show the item from database after certain time interval.
Code:
import React, { Component } from 'react'
export default class show_schedule extends Component {
render() {
state={
}
show_item_after_delete=()=>{
setTimeout(()=>{
axios.get(`http://127.0.0.1:8000/account/api/show_item/`).then(res=>{
console.log('delete schedule data ',res.data)
})
},500)
}
deleteHandler=()=>{
axios.delete(`http://127.0.0.1:8000/account/api/delete_item/${id}`).then(res=>{
console.log(res.data)
})
this.show_item_after_delete()
}
return (
<div>
<button onClick={this.deleteHandler}>Delete</button>
</div>
)
}
}

Recover right ID element in React Firebase App

I try to update data in react firebase application. Everything work fine, i can recover the right data in a modal, and modify them.
But, when I set my data to firebase (with a function "updateContent), my entire collection of item is delete because I did not specify the exact path of the selected item. So, to do that, I need to recover the ID of the selected Item in my function. My problem: I manage to retrieve all the information of my element, but not its ID. I try many thing, console.log every function with ID item, every thing it's okay except for my modal and my function "updateContent" (while the other information of my element is displayed without any problem)
Can you give me a little help ? Thank you in advance.
This is my code for each item, when function to pass the data from my Hit Component to my modal Component (modal is for modify item data):
function handleClick (hit, onEdit) {
onEdit({id: hit.objectID, marque: hit.marque, numero: hit.numero, reference: hit.reference, marquesuite: hit.marquesuite, cote: hit.cote})
}
const Hit = ({hit, onEdit}) =>
<div className="item" id={hit.objectID}>
<img src={hit.avatarURL} width={150} height={150}></img>
<h1 className="marque">{hit.marque}</h1>
<h3 className="numero">{hit.numero}</h3>
<h4 className="reference">{hit.reference}</h4>
<h4 className="marquesuite">{hit.marquesuite}</h4>
<p className="cote">{hit.cote}</p>
<button className="btn btn-warning" onClick={() => handleClick(hit, onEdit) }>Modifier</button>
<button className="btn btn-danger" onClick={() => removeToCatalogue(hit)}>Supprimer</button>
</div>
const Content = ({ onEdit, }) => {
const EnhancedHit = props =>
<Hit onEdit={ onEdit } { ...props } />
return (
<div className="text-center">
<Hits hitComponent={ EnhancedHit } />
</div>
)
}
And now, this is my modal component:
updateContent = (e) => {
e.preventDefault();
const catalogue = {
marque: this.state.marque,
marquesuite: this.state.marquesuite,
numero: this.state.numero,
reference: this.state.reference,
cote: this.state.cote,
id: this.state.key,
}
console.log(catalogue)
//firebase.database().ref(`catalogue`/).set(catalogue);
};
onOpenModal = (hit) => {
this.setState({ open: true, id: hit.objectID, marque: hit.marque, numero: hit.numero, reference: hit.reference, marquesuite: hit.marquesuite, cote: hit.cote });
console.log(hit.marque, hit.id)
};
onCloseModal = () => {
this.setState({ open: false });
};
onInputChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
render (){
const { open } = this.state;
<h1 className="text-center">Catalogue de capsule</h1>
<InstantSearch
apiKey="xxx"
appId="xxx"
indexName="xxx>
<SearchBox translations={{placeholder:'Rechercher une capsule'}} width="500 px"/>
<Content onEdit={this.onOpenModal}/>
<Modal open={open} onClose={this.onCloseModal} center>
<form onSubmit={this.updateContent} key={this.state.objectID}>
<h2>Modification de la capsule :</h2>
<p>Marque de la capsule:<input type="text" class="form-control" name="marque" value={this.state.marque} onChange={this.handleChange}></input></p>
<p>Numéro de la capsule:<input type="text" class="form-control" name="numero" value={this.state.numero} onChange={this.handleChange}></input></p>
<p>Référence de la capsule:<input type="text" class="form-control" name="marquesuite" value={this.state.marquesuite} onChange={this.handleChange}></input></p>
<p>Référence de la capsule (suite):<input type="text" class="form-control" name="reference" value={this.state.reference}onChange={this.handleChange}></input></p>
<p>Cote de la capsule:<input type="text" class="form-control" name="cote" value={this.state.cote}onChange={this.handleChange}></input></p>
<button className="btn btn-success">Mettre à jour</button>
</form>
</Modal>
</InstantSearch>
I find the solution. It was just given the same name in id props like this:
onEdit({objectID: hit.objectID ...})
onOpenModal = (hit) => {
this.setState({ open: true, objectID: hit.objectID, ... });
};

Component not re rendering even after calling the setState

I have a react component in which user can upload Image and he's also shown the preview of uploaded image. He can delete the image by clicking delete button corresponding to Image. I am using react-dropzone for it. Here's the code:
class UploadImage extends React.Component {
constructor(props) {
super(props);
this.onDrop = this.onDrop.bind(this);
this.deleteImage = this.deleteImage.bind(this);
this.state = {
filesToBeSent: [],
filesPreview: [],
printCount: 10,
};
}
onDrop(acceptedFiles, rejectedFiles) {
const filesToBeSent = this.state.filesToBeSent;
if (filesToBeSent.length < this.state.printCount) {
this.setState(prevState => ({
filesToBeSent: prevState.filesToBeSent.concat([{acceptedFiles}])
}));
console.log(filesToBeSent.length);
for (var i in filesToBeSent) {
console.log(filesToBeSent[i]);
this.setState(prevState => ({
filesPreview: prevState.filesPreview.concat([
<div>
<img src={filesToBeSent[i][0]}/>
<Button variant="fab" aria-label="Delete" onClick={(e) => this.deleteImage(e,i)}>
<DeleteIcon/>
</Button>
</div>
])
}));
}
} else {
alert("you have reached the limit of printing at a time")
}
}
deleteImage(e, id) {
console.log(id);
e.preventDefault();
this.setState({filesToBeSent: this.state.filesToBeSent.filter(function(fid) {
return fid !== id
})});
}
render() {
return(
<div>
<Dropzone onDrop={(files) => this.onDrop(files)}>
<div>
Upload your Property Images Here
</div>
</Dropzone>
{this.state.filesToBeSent.length > 0 ? (
<div>
<h2>
Uploading{this.state.filesToBeSent.length} files...
</h2>
</div>
) : null}
<div>
Files to be printed are: {this.state.filesPreview}
</div>
</div>
)
}
}
export default UploadImage;
My Question is my component is not re-rendering even after adding or removing an Image. Also, I've taken care of not mutating state arrays directly. Somebody, please help.
Try like this, I have used ES6
.

React-tooltip rendering two times

I have this component form react-tooltip where I pass some props and it creates the tooltip. I want the place of the tooltip to be "top" on default, but when I pass the props to be in a different place, to change it.
class Tooltip extends PureComponent {
render() {
const { text, element, type, place, className } = this.props;
return (
<div data-tip={text} className="m0 p0">
{element}
<ReactTooltip
type={type}
place={place}
effect="solid"
className={className}
html
/>
</div>
);
}
}
Tooltip.defaultProps = {
type: 'info',
place: 'top',
className: 'tooltip-top',
};
Tooltip.propTypes = {
text: PropTypes.string.isRequired,
element: PropTypes.element.isRequired,
type: PropTypes.string,
place: PropTypes.sring,
className: PropTypes.sring,
};
export default Tooltip;
Then I have this other component where I pass some props to the Tooltip component and I just want this only component to be placed on the bottom.
<Tooltip
type="warning"
place="bottom"
className="tooltip-bottom"
text={
'Ingrese los datos de la información financiera histórica de su compañía en la plantilla'
}
element={
<div className={`center mt3 ${styles.optionButton}`}>
<NavLink
className="btn btn-primary"
to={`${path}/manual-upload`}
>Continuar</NavLink>
</div>
}
/>
The problem is that is rendering in the bottom but also on the top. How can I make this to only appear on the bottom (in this component and the rest of the tooltips on the top). Thanks ;)
If you use <ReactTooltip /> inside a loop then you will have to set a data-for and id for each one.
const Tooltip = ({ children, data }) => {
const [randomID, setRandomID] = useState(String(Math.random()))
return (
<>
<div data-tip={data} data-for={randomID}>{children}</div>
<ReactTooltip id={randomID} effect='solid' />
</>
)
}
export default Tooltip
I ran into this issue today as well, I was able to get it resolved, this might not be relevant to you anymore, but for people looking:
I had this issue with data-for and id as well, the solution for me
was to set a more unique identifier/a combination of a word and a
variable that I was getting from the parent component (i.e.
id=`tooltip-${parent.id}`).
Heres the same
issue.

React: When the user interacts with the checkbox control, the state of the item should be updated from NEW to RESERVED

ProductList component has a child component ProductRow , all that needs to happen is when I click the checkbox inside ProductRow component the value of the checkbox should change to RESERVED from NEW (which is passed down by props).
Do I have to use redux, just because of this?
More context ProductList is a child of ShoppingCart component which looks like this:
const ShoppingCart = React.createClass({
propTypes: {
shoppingCartData: PropTypes.object.isRequired
},
render () {
const {assignee, customer, status, assignedAt, items, placedAt} = this.props.shoppingCartData.data
return (
<div>
<Header assignee={assignee} />
<PersonalInfo customer={customer} assignedAt={assignedAt} />
<CartStatus status={status} customer={customer} placedAt={placedAt} />
<ProductList items={items} />
</div>
)
}
})
export default ShoppingCart
ProductList.js
const ProductList = React.createClass({
propTypes: {
items: PropTypes.array.isRequired
},
handleProductCheckBoxClick (e) {
console.log('handleChange', e.target.value)
},
render () {
const {items} = this.props
const handleProductCheckBoxClick = this.handleProductCheckBoxClick
return (
<div>
{
items.map((item) => {
return (
<ProductRow key={item.id} onChange={handleProductCheckBoxClick} item={item} />
)
})
}
</div>
)
}
})
ProductRow.js
const ProductRow = React.createClass({
propTypes: {
item: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired
},
render () {
const { code, name, imageUrl, description } = this.props.item.product
const {status} = this.props.item
const {onChange} = this.props
return (
<div>
<label htmlFor={code}>
<input type='checkbox' id={code} onChange={onChange} value={status} />
<img src={imageUrl} />
<div className='name'>{name}</div>
<div className='description'>{description}</div>
</label>
</div>
)
}
})
ShoppingCartData
{
"data":{
"id":"0335c8ed-3b41-4bc0-9fc5-adbaeeba6ed2",
"productGroup":"7307",
"status":"INPROGRESS",
"assignee":{
"id":"9018418",
"name":"Mark"
},
"items":[
{
"id":25,
"sequence":1,
"status":"NEW",
"quantity":1,
"product":{
"code":"730719067100000",
"name":"Boltaart Bosbessen",
"description":"Overheerlijke Boltaart met Bosbessen uit de keuken van de Bijenkorf.",
"price":17.95,
"imageUrl":"//placehold.it/57/ffffff/000000"
}
},
{
"id":26,
"sequence":1,
"status":"NEW",
"quantity":1,
"product":{
"code":"730719067300000",
"name":"Aarbeien Boltaart",
"description":"Biscuitdeeg met aardbeienbavaroise, afgemaakt met aardbeiengelei en chocoladegalletjes.",
"price":17.95,
"imageUrl":"//placehold.it/57/ffffff/000000"
}
},
{
"id":27,
"sequence":1,
"status":"NEW",
"quantity":1,
"product":{
"code":"730719067200000",
"name":"Truffel Boltaart",
"description":"Chocolade mousse en biscuitdeeg gevuld met koffierumsaus en feuilletine, overgoten met pure chocoladegelei en gegarneerd met een krul van pure chocolade en chocoladegalletjes.",
"price":17.95,
"imageUrl":"//placehold.it/57/ffffff/000000"
}
}
],
"assigned":true,
"assignedAt":"2016-05-25 10:30",
"orderId":"36480157_CKS_N01",
"customer":{
"id":"00005152",
"email":"alan.form#email.nl",
"name":"Alan Ford",
"phoneNumber":"+31123456789"
},
"placedAt":"2016-05-24 09:00",
"numberOfItems":3
}
}
What you can do is assign props you get from the parent as the state of the component. And, use that state in the render function. And when you update the state of the component, the component will update.
But, remember that assigning props to the state is considered anti-pattern: https://stackoverflow.com/a/28785276/1553053
My suggestion is start using Redux or Alt. Alt is fairly easy to get started. They will allow you to handle application wide state and this kind of situation can be handled in much easier and nicer manner.

Categories

Resources