0

I have a collection of components with and add and remove button.

I'd like to hide/grey out these buttons when the collection is too small and too big.

This bit of code picked up from here seems like it would do the job :

render() {
    return (
        { this.props.isGreaterThanOne && (
            <div>
                this only shows up if the checkboxField Field is checked
            </div>
        ) }
    );
}

And I could simply update a boolean within my increment and decrement functions like so :

let isGreaterThanOne = true;
this.setState({
    collection: this.state.collection.splice(this.state.collection, this.state.collection.length - 1),
});
if (this.state.collection.length > 1) {
    isGreaterThanOne = true;
} else {
    isGreaterThanOne = false;
}

    return { isGreaterThanOne };

Now I'm consious the above is probably as garbage as it gets. All suggestions welcome. I think the variable should be decalred globally but I don't know how to do it.

Basically I just want there to be a variable that is set to false whenever the remove line should be hid (only one line left) and true when there are two lines or more.

Same deal with another variable traking when the collection reaches 15 or something.

Right now even if I just declare isGreaterThanOne as a global const equal to true the div doesn't show up.

As per @Denialos 's demand here is my full component (with his suggestions) :

/* ************************************* */
/* ********       IMPORTS       ******** */
/* ************************************* */
import React, { Component } from 'react';
import UUID from 'node-uuid';
import { Card, CardBlock, Button, InputGroup, Input } from 'reactstrap';
import ProviderInfos from '../ProviderInfos/ProviderInfos';

/* ************************************* */
/* ********      VARIABLES      ******** */
/* ************************************* */

/* ************************************* */
/* ********      COMPONENT      ******** */
/* ************************************* */
export default class PretzelStandComponent extends Component {

    constructor(props) {
        super(props);
        this.state = { 
            inputPretzel: [],
            isGreaterThanOne: true
            };
        this.incrementPretzel = this.incrementPretzel.bind(this);
        this.decrementPretzel = this.decrementPretzel.bind(this);
    }

    componentDidMount() {
        this.incrementPretzel();
    }

    incrementPretzel() {
        const uuid = require('uuid/v1');
        uuid();
        const inputPretzel = this.state.inputPretzel;
        if (this.state.inputPretzel.length > 1) {
            this.state.isGreaterThanOne = true;
        } else {
            this.state.isGreaterThanOne = false;
        }
        this.setState({
            inputPretzel: inputPretzel.concat(<InputGroup>
                <Input placeholder="Pretzel" key={uuid} /><ProviderInfos /></InputGroup>),
        });
    }

    decrementPretzel() {
        if (this.state.inputPretzel.length > 1) {
            this.state.isGreaterThanOne = true;
        } else {
            this.state.isGreaterThanOne = false;
        }
        this.setState({
            inputPretzel: this.state.inputPretzel.splice(this.state.inputPretzel, this.state.inputPretzel.length - 1),
        });
    }

    render() {
        return (
            <Card>
                <CardBlock className="main-table">
                    <fieldset>
                        <legend>Pretzels</legend>
                        {this.state.inputPretzel}
                        <button onClick={this.incrementPretzel}>Ajouter un Pretzel</button>
                        { this.props.isGreaterThanOne && (
                           <div>
                               <button onClick={this.decrementPretzel}>Enlever un Pretzel</button>
                           </div>
                         ) }
                    </fieldset>
                    <Button color="secondary">Options</Button>{' '}
                    <Button id="btn">Exécuter</Button>
                </CardBlock>
            </Card>
        );
    }
}
tatsu
  • 2,316
  • 7
  • 43
  • 87

2 Answers2

1

Problem here is you try to mutate a prop in your component. As already said, Never mutate your state or props this way.

here is a possible solution to your problem :

render() {
const { inputPretzel } = this.state;
const isGreaterThanOne  = inputPretzel && inputPretzel.length > 0;
return (
    <Card>
        <CardBlock className="main-table">
            <fieldset>
                <legend>Pretzels</legend>
                {inputPretzel}
                <button onClick={this.incrementPretzel}>Ajouter un Pretzel</button>
                {isGreaterThanOne  && (
                    <div>
                        <button onClick={this.decrementPretzel}>Enlever un Pretzel</button>
                    </div>
                ) }
            </fieldset>
            <Button color="secondary">Options</Button>{' '}
            <Button id="btn">Exécuter</Button>
        </CardBlock>
    </Card>
);

}

Isengrin
  • 26
  • 2
0

Don't mutate state directly, you should call setState.

NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains. setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate().

If mutable objects are being used and the logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

Font: What the difference of this.state and this.setstate in ReactJS?

Possible solution for your problem, Using immutability-helper:

import update from 'immutability-helper';
.....
.....
    incrementPretzel() {
        const uuid = require('uuid/v1');
        uuid();
        const inputPretzel = this.state.inputPretzel;
        if (this.state.inputPretzel.length > 1) {
            this.setState({ isGreaterThanOne: true });
         else {
            this.setState({ isGreaterThanOne: false });
        }
        this.setState({
            inputPretzel: inputPretzel.concat(<InputGroup>
                <Input placeholder="Pretzel" key={uuid} /><ProviderInfos /></InputGroup>),
        });
    }
decrementPretzel() {
    const inputPretzel = this.state.inputPretzel;
    if (this.state.inputPretzel.length > 1) {
       this.setState({ isGreaterThanOne: true });
    } else {
        this.setState({ isGreaterThanOne: false });
    }
  this.setState((prevState) => ({
    data: update(prevState.data, {$splice: [[-1, 1]]})
  })
}

render() {
        return (
            <Card>
                <CardBlock className="main-table">
                    <fieldset>
                        <legend>Pretzels</legend>
                        <button onClick={() => this.incrementPretzel}>Ajouter un Pretzel</button>
                        { this.state.isGreaterThanOne && 
                           <div>
                               <button onClick={() => this.decrementPretzel}>Enlever un Pretzel</button>
                           </div>
                         }
                    </fieldset>
                    <Button color="secondary">Options</Button>
                    <Button id="btn">Exécuter</Button>
                </CardBlock>
            </Card>
        );
    }
Yuri Pereira
  • 1,945
  • 17
  • 24