Bill
Bill

Reputation: 610

having trouble getting redux components to re-render

I have 2 components (a form for inputing values and a react-table component to display the inputed values) that I am putting on a dashboard. When I enter the values into the form to update the redux store, I can see the changes from redux tools however, the table component doesn't update until I go to a different page and come back. Anyone know what I am doing wrong?

Here is my reducer. I don't believe I am mutating the state here.

Reducer:

const keysReducerDefaultState = [];

export default (state = keysReducerDefaultState, action) => {
  switch (action.type) {
    case 'ADD_KEYS': 
      return [
        ...state,
        action.keyPair
      ];
    case 'REMOVE_KEYS':
      return state.filter(({ name }) => {
        return name !== action.name;
      });
    default:
      return state;
  }
}

Component 1

class KeysImportForm extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      // type validation
      name: "",
      publicKey: "",
      privateKey: "",
    };
    this.typeClick = this.typeClick.bind(this);
  }
  render() {
    const { classes } = this.props;
    return (
      // a form that takes in 3 fields, name, publickey and privatekey
    );
  }
}

const mapDispatchToProps = (dispatch) => ({
  addKeys: (keyPair) => dispatch(addKeys(keyPair))
});

export default withStyles(validationFormsStyle)(connect(undefined, mapDispatchToProps)(KeysImportForm));

Component 2

class KeysTable extends React.Component {
  constructor(props) {
    super(props);
    const data = props.keys.map((prop, key) => {
      return {
        id: key,
        name: prop.name,
        publicKey: prop.publicKey,
        privateKey: prop.privateKey,
      };
    });
    this.state = {
      data
    };
  }
  render() {
    const { classes } = this.props;
    return (
      <GridContainer>
        <GridItem xs={12}>
          <Card>
            <CardHeader color="primary" icon>
              <CardIcon color="primary">
                <Assignment />
              </CardIcon>
              <h4 className={classes.cardIconTitle}>Key Pairs</h4>
            </CardHeader>
            <CardBody>
              <ReactTable
                data={this.state.data}
                filterable
                columns={[
                  {
                    Header: "Name",
                    accessor: "name",
                    minWidth: 10
                  },
                  {
                    Header: "Public Key",
                    accessor: "publicKey",
                    minWidth: 50
                  },
                  {
                    Header: "Private Key",
                    accessor: "privateKey",
                    minWidth: 50
                  },
                  {
                    Header: "Action",
                    accessor: "action",
                    minWidth: 10,
                    sortable: false,
                    filterable: false
                  }
                ]}
                defaultPageSize={10}
                showPaginationTop
                showPaginationBottom={false}
                className="-striped -highlight"
              />
            </CardBody>
          </Card>
        </GridItem>
      </GridContainer>
    );
  }
}

const mapDispathToProps = (dispatch, props) => ({
  removeKeys: (id) => dispatch(removeKeys(id))
});

const mapStateToProps = (state) => {
  return {
    keys: state.keys
  }
}

export default withStyles(styles)(connect(mapStateToProps, mapDispathToProps)(KeysTable));

Dashboard

class Dashboard extends React.Component {
  state = {
    value: 0
  };
  handleChange = (event, value) => {
    this.setState({ value });
  };
  handleChangeIndex = index => {
    this.setState({ value: index });
  };
  render() {
    const { classes } = this.props;
    return (
      <div>
        <KeysImportForm/>
        <KeysTable/>
      </div>
    );
  }
}

Dashboard.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(dashboardStyle)(Dashboard);

Upvotes: 0

Views: 25

Answers (1)

J. Hesters
J. Hesters

Reputation: 14766

I'm not 100% sure, but it looks like you are having the following error:

In your constructor you do a (unnecessary) copy of you props to your state, which introduces the error and defeats the purpose of Redux:

const data = props.keys.map((prop, key) => {
  return {
    id: key,
    name: prop.name,
    publicKey: prop.publicKey,
    privateKey: prop.privateKey,
  };
});

This causes your data to only update when your constructor is called, which is when your component mounts (a.k.a. you reload your page).

Instead use your props directly as your data. Redux will cause your component to re-render every time the state changes.

Upvotes: 1

Related Questions