I have a function that is sent as a prop to a child-component. When the funcion gets called and the state is updated in the function the parent-component dont get updated. Why is this?
class Admin extends React.Component{
constructor(props) {
super(props);
this.viewOrderCommand=this.viewOrderCommand.bind(this);
this.state = {
cmd: 0,
stillLoading: true
};
}
viewOrderCommand(cmd, id) {
if (id > 0) {
this.setState({cmd, id});
}
}
render() {
const { isLoading, apiToken } = this.props;
let userInformationNode = <LoadingSpinner isLoading={true} />;
console.log('OrderSearchData this.state',this.state.cmd);
if (this.state.cmd && this.state.cmd > 0) {
userInformationNode =<NewUser viewOrderCommand={this.viewOrderCommand} id={this.state.id} apiToken={apiToken} />;
} else {
userInformationNode = <CurrentUser apiToken={apiToken} viewOrderCommand={this.viewOrderCommand}/>;
}
if (isLoading) {
userInformationNode=undefined;
}
return (
<Tabs defaultActiveKey="current" id="admin-user-tabs">
<Tab eventKey="current" title="Current Users">
{userInformationNode}
</Tab>
<Tab eventKey="new" title="New Users">
<NewUser apiToken={this.props.apiToken} />
</Tab>
<Tab eventKey="create" title="Create New User">
<CreateUser apiToken={this.props.apiToken} />
</Tab>
</Tabs>
);
}
}
export default Admin;¨
This is the child component from where I call the function viewOrderCommand in the Admin-component.
import React from 'react';
import NPPanel from '../../NPPanel';
import { Col, Row } from 'react-bootstrap';
import "react-table/react-table.css";
import 'react-select/dist/react-select.css';
import 'bootstrap/dist/css/bootstrap.css';
import constants from '../.././util/constants';
import axios from 'axios';
import { getFilteredData, setDataForExpansion, getExpander } from '../../gridHelpers/gridHelpers';
import NPHelpButton from '../../NPHelpButton';
import NPReactTable from '../../NPReactTable';
import LoadingSpinner from '../../LoadingSpinner';
import './style.less';
const { API_BASE_URL } = constants;
class CurrentUser extends React.Component{
constructor(props) {
super(props);
this.tell = this.tell.bind(this);
this.state = { users: undefined, loaded:false };
this.getUsers = this.getUsers.bind(this);
this.handleSelectChange = this.handleSelectChange.bind(this);
this.getUsers('', true);
}
tell(txt, row){
setDataForExpansion(txt, row, this.props.apiToken, this);
}
clearCurrentExpandforAll(){
let d = getFilteredData(this.reactTable.getReactTable());
this.currentExpand = '';
d.forEach(dt => {
dt.TAG = undefined;
});
}
handleSelectChange(evt, item, row){
if (item && row && row.original) {
let selIndex=evt.currentTarget.selectedIndex;
evt.currentTarget.selectedIndex=0;
this.props.viewOrderCommand(selIndex, row.original.Id);
}
}
getcolumns() {
const helpNode = (
<div>
...
</div>
);
return ([
{
Header: "User information",
headerStyle: { background: '#dedede' },
columns: [
{
Header: "",
maxWidth: 30,
Filter: ({ filter, onChange }) =>
<NPHelpButton content={helpNode} title="Help" />,
Cell: (row) =>
{
console.log('row',row);
return <span>
<select className='tst myopt handy' onChange={evt => { this.handleSelectChange(evt, evt.target.value, row, this);}}>
<option value="">...</option>
<option value="CreateNew">Create new</option>
<option value="Edit">Modify this user</option>
</select>
</span>
}
},
{
Header: "Username",
accessor: "Email",
},
{
expander: true,
width: 35,
Expander: ({ isExpanded, ...row }) =>
getExpander(row,'ClientCodeRegional',this,isExpanded),
style: {
cursor: "pointer",
textAlign: "center",
userSelect: "none"
},
},
]
},
]);
}
getUsers() {
const header = {
'Authorization': 'Bearer ' + this.props.apiToken,
'Accept': 'application/octet-stream'
};
let self = this;
self.setState({ isLoading: true });
axios.get(API_BASE_URL + 'Admin/GetUsers', { headers: header })
.then(result => {
console.log(result.data);
const users = result.data.filter(item => {
return item.Settings && item.Settings.HasAccess === true;
})
self.setState({isLoading: false, loaded: true, users: users, expanded: {} });
}).catch(response => { });
}
render(){
const users = this.state.users;
if (!users || this.state.isLoading) {
return <LoadingSpinner isLoading={true} />
}
return(
<NPPanel>
<Row>
<Col sm={12}>
<Row>
<Col sm={12}>
{this.state.loaded?
<NPReactTable
className="np-react-table"
data={users}
ref={(r) => { this.reactTable = r }}
columns={this.getcolumns()}
defaultFilterMethod={(filter, row) =>
((row[filter.id] || '').toString().toUpperCase().includes(filter.value.toUpperCase()))}
filterable
filterAll
defaultPageSize={10}
// Controlled props
sorted={this.state.sorted}
page={this.state.page}
pageSize={this.state.pageSize}
expanded={this.state.expanded}
resized={this.state.resized}
filtered={this.state.filtered}
// Callbacks
onSortedChange={sorted => this.setState({ sorted, expanded: {} })}
onPageChange={
page => {
this.clearCurrentExpandforAll();
this.setState({ page, expanded: {} });
}
}
onPageSizeChange={(pageSize, page) => {
this.clearCurrentExpandforAll();
this.setState({ page, pageSize, expanded: {} });
}
}
onResizedChange={resized => this.setState({ resized })}
onFilteredChange={filtered => {
//this.clearCurrentExpandforAll();
this.setState({ filtered, page: 0, expanded: {} })
}
}
SubComponent={row => {
let r = row.original;
let t = 'EXP_' + r.TAG;
if (r.TAG && r.TAG !== '' && r[t]) {
return r[t];
}
}
}
/>
:null
}
</Col>
</Row>
</Col>
</Row>
</NPPanel>
);
}
}
export default CurrentUser;
When I debug the code I can se that the function gets called and the state is set but the re-rendering never occurs. I want the admin component to render the NewUser component instead of CurrentUser. Similar thing is done in another place in my code and it works there.
console.log(cmd, id)inside yourviewOrderCommandwhat shows, also do you get any errors?.stillLoadingstate orisLoadingprops is updated tofalse?