0

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.

4
  • If you put console.log(cmd, id) inside your viewOrderCommand what shows, also do you get any errors?. Commented Apr 5, 2019 at 9:33
  • The cmd shows '2' and the id a long string of numers and letters so that seems to work. I have a few warnings saying "Can only update a mounted or mounting component" but I dont think that is the main problem. Commented Apr 5, 2019 at 9:41
  • I want to re-render the Admin component when I call viewOrderCommand and set the state of Cmd. In my world the render function would then call the NewUser component instead of currentUser. Commented Apr 5, 2019 at 10:03
  • Have you made sure your stillLoading state or isLoading props is updated to false? Commented Apr 5, 2019 at 10:04

2 Answers 2

1

EDIT:

Your problem could be because cmd is not being set correctly. It seems like you might need to do this:

this.setState({cmd: id});
Sign up to request clarification or add additional context in comments.

5 Comments

Do you mean to CurrentUser or CreateUser?
currentuser.. soz
Does not seem to make any difference.
what does cmd print out as in the render method?
Actually, I discovered that the state was not updated correctly, cmd was still 0 after I called setState. Removing the initial state declaration in the constructor and setting this.setState({cmd: id}) solved the problem!
0

Is this not a typo?

viewOrderCommand(cmd, id) {   
    if (id > 0) {
        this.setState({cmd, id}); // is it supposed  to be {cmd: id}  ? 
    }     
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.