Re render component React table - reactjs

I am trying to re render a component. I have a refresh button and I want to clean all filters and sorting values when clicked.
The thing is that I can not make a re render, not even with forceUpdate(), it is doing NOTHING and I don't know why. Also, I tried with setState(), and nothing. What I want to happen is what happens when I change the page, it re renders the component. Please can anybody could help me? What am I doing wrong?
import React, { Component } from "react";
import DeleteComponent from "../components/DeleteComponent"
import ReactTable from 'react-table';
import { Link, withRouter } from 'react-router-dom';
import axios from "axios";
import { getJwt } from '../helpers/jwt'
import eye from '../img/eye.png'
import bin from '../img/bin.png'
import writing from '../img/writing.png'
class CustomReactTable extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
showDelete: false,
item: null,
pages: null,
totalItems: null,
loading: false,
state: {},
}
}
fetchData = (state) => {
this.setState({ state: state })
const jwt = getJwt()
if (!jwt) {
this.props.history.push('/login')
}
let config = {
headers: { 'Authorization': `Bearer ${jwt}` },
params: {
page: state.page,
pageSize: state.pageSize,
sorted: state.sorted,
filtered: state.filtered
}
}
this.setState({ loading: true })
axios.get(`http://localhost:3001/api/v1${this.props.location.pathname}`, config)
.then(response => {
console.log(response)
this.setState({
data: response.data.result,
loading: false
})
})
axios.get(`http://localhost:3001/api/v1${this.props.location.pathname}/count-documents`, config)
.then(response => {
this.setState({
totalItems: response.data.result,
pages: Math.ceil(response.data.result / state.pageSize)
})
})
}
loadOptions = () => {
this.props.columns.push({
Header: "",
Cell: (row) => [
// Find a better way to add unique key
<Link to={`${this.props.location.pathname}/${row.original._id}/show`} key={row.original._id} params={{ id: row.original._id }}><button className="btn-xs btn-outline-light"><img style={{ width: '1em' }} src={eye} /></button></Link>,
<Link to={`${this.props.location.pathname}/${row.original._id}/edit`} key={row.original._id + 'a'}><button className="btn-xs btn-outline-light"><img style={{ width: '1em' }} src={writing} /></button></Link>,
<button key={row.original._id + 'b'} className="btn-xs btn-outline-light" onClick={() => { this.onClickDeleteButton(row.original._id) }}><img style={{ width: '1em' }} src={bin} /></button>
]
})
}
loadFunctionalities = () => {
return (
<div className='functionalities-react-table'>
<span className='functionalities-add-item-table'>
<Link to={`${this.props.location.pathname}/add`}><button className="btn-sm btn-outline-success">Add new {this.props.modelName}</button></Link>
</span>
<span className='functionalities-refresh-table'>
<button className="btn-sm btn-outline-dark">Refresh table</button>
</span>
</div>
)
}
onClickDeleteButton = (id) => {
this.setState({ showDelete: true, item: id })
}
onCancelDeleteClick = () => {
this.setState({ showDelete: false })
}
componentDidMount() {
this.loadOptions()
}
reloadData = () => {
this.fetchData(this.state.state)
}
render() {
return (
<div className='main-content'>
{this.state.showDelete && (
<DeleteComponent reloadData={this.reloadData} onCancelDeleteClick={this.onCancelDeleteClick} item={this.state.item} />
)}
<h3>{`${this.props.modelName} (${this.state.totalItems})`}</h3>
{this.loadFunctionalities()}
<ReactTable
data={this.state.data}
columns={this.props.columns}
manual
onFetchData={this.fetchData}
defaultPageSize={10}
pages={this.state.pages}
style={{ fontSize: '0.9em' }}
>
</ReactTable>
<div className="total-records-tag">{this.props.modelName}: {this.state.totalItems}</div>
</div >
)
}
}
export default withRouter(CustomReactTable);

Related

Formio React Edit function does not take variable or state

I'm creating a custom Formio app using React and I'm trying to create a component that we can use to open previously created forms for editing. I use the component from Formio, and then try to pull the components and pass them to the components attribute, but it keeps telling me it's undefined. However, if I stringify it, and even import it using a variable or paste the exact string in, it works, but if I try to pass it to a variable or state, it won't work. Below is my code and any help is much appreciated. I feel like I've tried everything.
import { FormEdit, FormBuilder } from "react-formio";
import axios from "axios";
import AppLayout from "../pages/layout/appLayout";
import { Typography } from "#material-ui/core/";
import { Link } from "react-router-dom";
import { components } from "../formData";
export default class FormUpdate extends React.Component {
state = {
formName: "",
formTitle: "",
isFormSubmitted: false,
formComponents: {},
errorMsg: "",
};
componentDidMount() {
console.log("Id", this.props.formData);
axios
.get(
`https://awsid.execute-api.us-east-1.amazonaws.com/prod/form?formName=${this.props.formData.id}`,
{ crossDomain: true },
{
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
},
}
)
.then((res) => {
console.log(res.data.form.components);
this.setState({
formComponents: res.data.form.components[0],
});
})
.catch((error) => {
console.log(error);
this.setState({ errorMsg: "Error retrieving form data." });
});
}
updateForm = (form) => {
const payload = {
form,
};
console.log("Form Data:", form);
/* Code to fix JSON of select boxes component. If no default value is selected, default value attribute is deleted */
for (var key in payload.form.components) {
if (
form.components[key].defaultValue === "" ||
form.components[key].defaultValue === null ||
// form.components[key].defaultValue === false ||
form.components[key].defaultValue.hasOwnProperty("")
) {
console.log(
form.components[key].defaultValue + " is blank. Deleting attribute."
);
delete form.components[key].defaultValue;
}
console.log(form.components[key].defaultValue);
}
return axios
.put(
`https://awsid.execute-api.us-east-1.amazonaws.com/prod/form`,
payload,
{ crossdomain: true },
{
headers: {
"Content-type": "application/json",
},
}
)
.then((response) => {
console.log("Uploaded", response.data);
this.setState({
formName: response.data.id,
formTitle: response.data.title,
isFormSubmitted: true,
});
})
.catch((error) => {
console.log("Did not post: " + error);
});
};
handleFormNameChange = (evt) => {
const value = evt.target.value;
this.setState({
...this.state,
formName: value,
});
};
handleFormNameClick = async () => {
await this.setState({
formNameForm: false,
});
this.retrieveData(this.state.formName);
// console.log(this.state.formName);
};
listComponents = () => {
this.state.formComponents.map((item) => {
console.log(item);
// this.setState({ formComponents: item });
return item;
});
};
components = JSON.stringify(this.state.formComponents).replace(
/^\[(.+)\]$/,
"$1"
);
render() {
// const components = JSON.stringify(this.state.formComponents).replace(
// /^\[(.+)\]$/,
// "$1"
// );
// const allComponents = this.state.formComponents[0];
console.log(
JSON.stringify(this.state.formComponents).replace(/^\[(.+)\]$/, "$1")
);
console.log(this.state.formComponents);
console.log(components);
return (
<AppLayout>
<div className="container">
<link rel="stylesheet" href="styles.css" />
<link
rel="stylesheet"
href="https://unpkg.com/formiojs#latest/dist/formio.full.min.css"
/>
<link
href="https://fonts.googleapis.com/css2?family=Bangers&display=swap"
rel="stylesheet"
></link>
<main className="formEditContainer">
{this.state.isFormSubmitted === true ? (
<div className="fadePanel">
<Typography variant="h4" align="center">
Form Completed
</Typography>
<br />
<Typography variant="body1" align="center">
<b>
<i> To view form visit:</i>
</b>{" "}
<Link
to={`/openform/${this.state.formName}`}
className="links"
>
<small>{this.state.formTitle}</small>
</Link>
</Typography>
</div>
) : (
<div>
<Typography>
Form Name:
{this.props.formData.id}
</Typography>
<br />
<FormEdit
form={{
display: "form",
title: this.props.formData.id,
name: this.props.formData.id,
path: this.props.formData.id,
components: [components],
}}
saveText={"Save Form"}
saveForm={(form) => this.updateForm(form)}
>
<FormBuilder
form={{
display: "form",
title: this.props.formData.id,
}}
Builder={{}}
onUpdateComponent={{}}
/>
</FormEdit>
</div>
)}
<br />
<br />
</main>
</div>
</AppLayout>
);
}
}

I get an error when using reactjs useState

I am using reactjs. I am using the material-table to get the data with the editable table.
But I get an error like the picture, how can I fix this error?
I use useState for the edit settings of the table.
Please can you help with the error?
I do not receive any errors while receiving data. I just use editing on the table as active / inactive.
But
     const [, forceUpdate] = useState (false);
     const [data, setData] = useState (drBounty);
gives error for lines.
screenshot of the error and my source code below
import React, { Component, useState } from "react";
import withAuth from "../../components/helpers/withAuth";
import AlertMessageBox from "../../components/helpers/AlertMessageBox";
import { connect } from "react-redux";
import { Button, Col, Row, Table, Input } from "reactstrap";
import MaterialTable, { MTableEditRow } from "material-table";
import icons from '#material-ui/core/Icon';
import DeleteOutline from '#material-ui/icons/DeleteOutline';
import Edit from '#material-ui/icons/Edit';
class Bounty extends Component {
constructor(props) {
super(props);
this.state = {
isLoaded: true,
drBounty: [],
drList: [],
columns: [
{ title: 'Name', field: 'doctorName',
cellStyle:{padding: "1px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "1px"},
editComponent: (props) => (
<Input
type="text"
placeholder={props.columnDef.title}
defaultValue={props.value}
onChange={(e) => props.onChange(
this.setState({
doctorName: e.target.value
})
)}
/>
)
},
{ title: 'LastName', field: 'doctorLastName',
cellStyle:{padding: "1px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "5px"},
editComponent: (props) => (
<Input
type={"text"}
placeholder={"Doktor soyadı"}
defaultValue={props.value}
onChange={(e) => props.onChange(
this.setState({
doctorLastName: e.target.value
})
)}
/>
)
}
]
};
this.getBountyList = this.getBountyList.bind(this);
}
async componentDidMount() {
await fetch(
`${this.domain}/api/user/groupusers?groupCode=`+
this.props.account_profile.profile.profile.groupCode,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
console.log(json)
})
.catch(error => {
console.log(error)
return error;
});
}
async getBountyList(id) {
await fetch(`${this.domain}/api/bounty/list?groupCode=${this.props.account_profile.profile.profile.groupCode}&doctor=${id}`,{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
})
.then(res => {
console.log(res);
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
console.log(json)
})
.catch(error => {
console.log(error);
return error;
});
}
render() {
const {isLoaded, drList, drBounty} = this.state;
const [, forceUpdate] = useState(false);
const [data, setData] = useState(drBounty);
const isRowUpdating = (rowData, status) => {
rowData.tableData.editing = status ? "update" : undefined;
forceUpdate(status);
};
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn "}>
<Row>
<div> </div>
<Col sm={{span:1, offset:0.9}}>
<Table>
<thead>
<tr>
<th width={"20"} />
<th width={"50"}>Adı</th>
<th width={"70"}>Soyadı</th>
</tr>
</thead>
<tbody>
{
drList
.map(item => (
<tr key={item.id}>
<td>
<Button
block
outline
color="info"
onClick={() => this.getBountyList(item.id)}
>
Aç
</Button>
</td>
<td>{item.first_name} </td>
<td>{item.last_name}</td>
</tr>
))}
</tbody>
</Table>
</Col>
<MaterialTable
Icons={icons}
style={{height: "50", width: "50"}}
columns={ this.state.columns }
data={ this.state.drBounty }
actions={[
rowData => ({
icon: Edit,
tooltip: "Edit row",
onClick: (event, rowData) => {
isRowUpdating(rowData, true);
this.setState({
id: rowData.id,
user: rowData.user,
doctor: rowData.doctor,
doctorName: rowData.doctorName,
doctorLastName: rowData.doctorLastName,
totalBounty: rowData.totalBounty,
description: rowData.description,
customerName: rowData.customerName,
bountyDate: rowData.bountyDate,
createdDate: rowData.createdDate,
groupCode: rowData.groupCode
});
}
})
]}
components={{
EditRow: props => {
const newRowData = {
...drBounty, // *MUST INCLUDE tableData FROM ORIGINAL props.data!!*
id: "DEFAULT VALUES", // <-- // Set whatever default data you want here
doctorName: "ON EDIT" // <-- // (or pull from state, etc.. whatever you want)
};
return (
<MTableEditRow
{...props}
data={newRowData}
onEditingCanceled={(mode, rowData) => {
isRowUpdating(rowData, false);
}}
onEditingApproved={(mode, newData, oldRowData) => {
const dataCopy = [...drBounty];
const index = drBounty.indexOf(props.data);
dataCopy[index] = newData;
setData(dataCopy);
isRowUpdating(props.data, false);
}}
/>
);
}
}}
/>
</Row>
</div>
);
}
}
}
export default connect(withAuth( Bounty ));
You are trying to use the Hook (useState()) inside the render() method. Hooks can only be used inside of function components. However, you are using a class component so you have no need of this Hook.
Suggested Reading: https://reactjs.org/docs/hooks-state.html
Instead of using a Hook, you can use the following in your class component to accomplish the same results. Let's have a look :)
Initialize State in Constructor
this.state = { foo: bar };
You have already done this!
Update State with this.setState()
const [data, setData] = useState(drBounty);
Becomes ..
this.setState({data:drBounty});
However, you want to update the drBounty prop that you set up in the constructor, so you will want something more like this ..
this.setState({drBounty:someData})
Since that prop is an array, you will most likely want to spread (...) that data using the current array.
Re-Render without Updating State
As for your other implementation of useState() it appears you want to re-render without making any updates to state.
const [, forceUpdate] = useState(false);
However, instead you will want to simply use ...
this.render()

Reactjs: How to properly fetch each users record from database on pop button click using Reactjs

The code below shows each user info on users list button click.
Now I want fetch each users record from database on users list button click.
In the open() function, I have implemented the code below
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
}
In class OpenedUser(), I have initialize in the constructor the code below
chatData: []
In the render method have implemented the code
<b> Load Message from Database for each user ({this.state.chatData1})</b>
<div>
{this.state.chatData.map((pere, i) => (<li key={i}>{pere.lastname} - {pere.id}----- {pere.username}</li>))}
</div>
Here is my Issue:
My problem is that the Axios Api is getting the result but am not seeing any result in the render method.
but I can see it in the console as per code below
Array(1)
0: {id: "1", firstname: "faco", lastname: "facoyo"}
length: 1
Here is an example of json api response.
[{"id":"1","firstname":"faco","lastname":"facoyo"}]
Here is the full code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import { Link } from 'react-router-dom';
import axios from 'axios';
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button onClick={() => this.open(this.props.data.id,this.props.data.name)}>{this.props.data.name}</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
chatData: [],
hidden: false,
};
}
componentDidMount(){
} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b> Load Message from Database for each user ({this.state.chatData1}) </b>
<div>
{this.state.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</div>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
],
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/apidb_react/search_data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
// end axios api call
this.setState((prevState) => ({
activeIds: prevState.activeIds.find((user) => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
}
close = id => {
this.setState((prevState) => ({
activeIds: prevState.activeIds.filter((user) => user !== id),
}));
};
renderUser = (id) => {
const user = this.state.data.find((user) => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser key={user.id} data={user} close={this.close}/>
)
}
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map((id) => this.renderUser(id)) }
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
The problem is you're making the request in the App component and storing in state but you're trying to access the state in a child component so it will never actually read the data.
To fix this you need to pass in the chat data via prop
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
Note: In my runnable example, I've replaced your api endpoint with a mock api promise.
const mockApi = () => {
return new Promise((resolve, reject) => {
const json = [{ id: "1", firstname: "faco", lastname: "facoyo" }];
resolve(json);
});
};
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button
onClick={() => this.open(this.props.data.id, this.props.data.name)}
>
{this.props.data.name}
</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
hidden: false
};
}
componentDidMount() {} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b>
{" "}
Load Message from Database for each user ({this.state.chatData1}
){" "}
</b>
<ul>
{this.props.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</ul>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
chatData: [],
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
]
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id, name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: "id",
uname: "name"
};
// this.setState({ loading_image: true }, () => {
// axios
// .post("http://localhost/apidb_react/search_data.php", { user_data })
// .then(response => {
// this.setState({
// chatData1: response.data[0].id,
// chatData: response.data,
// loading_image: false
// });
// console.log(this.state.chatData);
// alert(this.state.chatData1);
// })
// .catch(error => {
// console.log(error);
// });
// });
this.setState({ loading_image: true }, () => {
mockApi().then(data => {
this.setState({
chatData1: data[0].id,
chatData: data,
loading_image: false
});
});
});
// end axios api call
this.setState(prevState => ({
activeIds: prevState.activeIds.find(user => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
};
close = id => {
this.setState(prevState => ({
activeIds: prevState.activeIds.filter(user => user !== id)
}));
};
renderUser = id => {
const user = this.state.data.find(user => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
);
};
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map(id => this.renderUser(id))}
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I see a few missing points in your code namely you are using li without ul which is a kind of invalid markup, then you have mapping for .username which is undefined field according to response which may also throw error.

react-photo-gallery don't change photos via state

The photo object is not changing in the Gallery component via state.
I created a "folder gallery", a multi gallery component to render a new one if you select it by click.
See the demonstration:
https://codesandbox.io/s/50wr02n8q4
github issue:
https://github.com/neptunian/react-photo-gallery/issues/118
Envs:
react-photo-gallery: 6.2.2
react: 16.6.3
npm: 6.4.1
See the code below:
const folderPhotos = [
{
title: "Gallery one",
photos: [
{
src: "https://source.unsplash.com/2ShvY8Lf6l0/800x599"
},
{
src: "https://source.unsplash.com/Dm-qxdynoEc/800x799"
},
{
src: "https://source.unsplash.com/qDkso9nvCg0/600x799"
}
]
},
{
title: "Gallery two",
photos: [
{
src: "https://source.unsplash.com/iecJiKe_RNg/600x799"
},
{
src: "https://source.unsplash.com/epcsn8Ed8kY/600x799"
},
{
src: "https://source.unsplash.com/NQSWvyVRIJk/800x599"
}
]
}
];
The photoProps dimensions object:
const photoProps = {
width: 1,
height: 1
};
The internal component here:
<Gallery
columnsLength={6}
photosObj={folderPhotos}
photoProps={photoProps}
withLightbox={true}
/>
Now the Gallery component:
import _ from "lodash";
import React, { Component, Fragment } from "react";
import Gallery from "react-photo-gallery";
import Lightbox from "react-images";
export class PhotoGallery extends Component {
constructor(props) {
super(props);
// Bindables
this.showGallery = this.showGallery.bind(this);
this.openLightbox = this.openLightbox.bind(this);
this.closeLightbox = this.closeLightbox.bind(this);
this.goToPrevious = this.goToPrevious.bind(this);
this.goToNext = this.goToNext.bind(this);
}
state = {
photosObj: [],
currentImage: 0,
lightboxIsOpen: false
};
async showGallery(itemObj, photoProps) {
let photosObj = [];
if (!_.isEmpty(itemObj)) {
photosObj = await Object.keys(itemObj)
.map(i => itemObj[i])
.map(item => ({
...item,
width: photoProps.width,
height: photoProps.height
}));
this.setState({
photosObj
});
console.log("-- props: ", this.state.photosObj);
}
}
openLightbox(event, obj) {
this.setState({
currentImage: obj.index,
lightboxIsOpen: true
});
}
closeLightbox() {
this.setState({
currentImage: 0,
lightboxIsOpen: false
});
}
goToPrevious() {
this.setState({
currentImage: this.state.currentImage - 1
});
}
goToNext() {
this.setState({
currentImage: this.state.currentImage + 1
});
}
render() {
const { columnsLength, photosObj, photoProps, withLightbox } = this.props;
return (
<div className="section-body">
<div className="content-col-info">
<ul className="list-mentors w-list-unstyled">
{photosObj.map((itemObj, i) => (
<li key={i}>
<span
className="mentors-item w-inline-block"
onClick={() => this.showGallery(itemObj.photos, photoProps)}
>
<div>{itemObj.title}</div>
</span>
</li>
))}
</ul>
</div>
<div className="content-col-info">
{!_.isEmpty(this.state.photosObj) && (
<Gallery
columns={columnsLength}
photos={this.state.photosObj}
onClick={withLightbox ? this.openLightbox : null}
/>
)}
{!_.isEmpty(this.state.photosObj) && withLightbox && (
<Lightbox
images={this.state.photosObj}
onClose={this.closeLightbox}
onClickPrev={this.goToPrevious}
onClickNext={this.goToNext}
currentImage={this.state.currentImage}
isOpen={this.state.lightboxIsOpen}
/>
)}
</div>
</div>
);
}
}
export default PhotoGallery;
EDIT - I updated the Gallery props
I fix the Gallery component props of the example too.
loadGallery(columnsLength) {
import("./photo-gallery").then(Gallery => {
console.log("-- load gallery: ", this.state.photosObj);
return (
<Gallery.default
columnsLength={columnsLength}
photosObj={this.state.photosObj}
withLightbox={true}
/>
);
});
}
And to call this:
{!_.isEmpty(this.state.photosObj) && this.loadGallery(columnsLength)}
References:
Intro to Dynamic import() in Create React App
React images
Since photos option is required in Gallery.js (Library)
Gallery.propTypes = {
photos: _propTypes2.default.arrayOf(_Photo.photoPropType).isRequired,
direction: _propTypes2.default.string,
onClick: _propTypes2.default.func,
columns: _propTypes2.default.number,
margin: _propTypes2.default.number,
ImageComponent: _propTypes2.default.func
};
Pass "photos={this.state.photosObj}" in <Gallery /> of Gallery.js (your js file) as follows:
Code:
<Gallery
columnsLength={columnsLength}
photosObj={this.state.photosObj}
photos={this.state.photosObj}
withLightbox={true}
/>
I am not sure why you pass other options.

React-Native setState not updating during fetch()

I have 3 records in my table, I can see the app fetches record to my remote because I console.log the response. My problem is that it will not display the item.
I know I defined correctly the column in FlatList because If I will set the per_page=1 which means pull 1 record every request. It will display but 2 records only will display the last record will not, if I set to per_page=30 nothing displays. is there a problem in my setState() during the response ?.I heard that setSate is not mutable..how can I apply the updater function of setsate in my code.?...I am still fresh on react native I hope someone will help me here.
I tried to do this but no luck!..also is this will matter that I use react-redux in my other page then in this screen I did not use only handling of state. ?...please help me react-native experts.
this.setState({
page: this.getParameterByName('page', res.next_page_url),
data: this.state.page === 1 ? res.data : [...this.state.data, ...res.data],
error: res.error || null,
loading: false,
refreshing: false,
last_page: res.last_page
},()=>{
return this.state;
});
Here is my complete code
import React, { Component } from 'react';
import {ScrollView, Text, View, Button, FlatList, ActivityIndicator} from 'react-native';
import { List, ListItem, Icon } from "react-native-elements";
import {connect} from "react-redux";
import numeral from "numeral";
import Moment from 'react-moment';
import moment from 'moment';
class Screen1 extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
page: 1,
per_page: 30,
order_by:'id',
sort_by:'asc',
error: null,
refreshing: false,
param:'',
last_page:''
};
}
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const {page, per_page,order_by,sort_by } = this.state;
const url = `http://myapp.com/api/mobile/credit?page=${page}&api_token=${this.props.token}&per_page=${per_page}&order_by=${order_by}&sort_by=${sort_by}`;
console.log("the url",url);
this.setState({ loading: true });
setTimeout(()=>{
fetch(url)
.then(res => res.json())
.then(res => {
console.log("the page is =",this.getParameterByName('page',res.next_page_url));
this.setState({
page:this.getParameterByName('page',res.next_page_url),
data: this.state.page === 1 ? res.data : [...this.state.data,...res.data],
error: res.error || null,
loading: false,
refreshing: false,
last_page: res.last_page
});
})
.catch(error => {
this.setState({ error, loading: false });
});
},1500);
};
handleRefresh = () => {
if( this.state.page) {
if (this.state.page <= this.state.last_page) {
this.setState(
{
refreshing: true,
page: this.state.page
},
() => {
this.makeRemoteRequest();
}
);
}
}
};
getParameterByName = (name,url) =>{
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
let regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return parseInt(decodeURIComponent(results[2].replace(/\+/g, " ")), 10);
};
handleLoadMore = () => {
if( this.state.page){
if( this.state.page <= this.state.last_page ){
this.setState(
{
page: this.state.page
},
() => {
this.makeRemoteRequest();
}
);
}else{
console.log("cannot handle more",this.state.page)
}
}else{
console.log("page is null");
}
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
marginLeft: "14%"
}}
/>
);
};
renderHeader = () => {
return (
<View >
<Text h1
style={{
color: 'blue',
fontWeight: 'bold',
textAlign: 'center',
fontSize: 30,
backgroundColor: "#CED0CE",
}}
>{ numeral(this.props.thetotalcredit).format("#,##0.00") }</Text>
</View>
);
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
borderColor: "#CED0CE"
}}
>
<ActivityIndicator animating size="large" />
</View>
);
};
render() {
return (
<FlatList
data={this.state.data}
keyExtractor = {(item, index) => index.toString()}
renderItem={({ item }) => (
<ListItem
title= { numeral(item.amountcredit).format("#,##0.00") }
subtitle= { moment(item.creditdate).format("MMM DD, YYYY") }
containerStyle={{ borderBottomWidth: 0 }}
/>
)}
extraData={this.state.data}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.5}
stickyHeaderIndices={[0]}
/>
);
}
}
const mapStateToProps = (state) => {
return {
username: state.auth.username,
token:state.auth.token,
thetotalcredit:state.auth.total_credit
};
};
export default connect(mapStateToProps)(Screen1);

Resources