Waseem
Waseem

Reputation: 577

How to make React Component call a function on every state change?

With this component, the getDisplay gets called on every update as usual (and so when clicking the becomes hidden):

class Example extends React.Component {
    constructor(props) {
        super(props);
        this.state = { show: true }
    }
    getDisplay = () => this.state.show ? 'block' : 'none';
    getStyle = () => { { display: this.getDisplay() } }
    render = () => <div style={{ display: this.getDisplay() }} onClick={() => { console.log('clicked'); this.setState({ show: false }) }}>
        <p>TEST</p>
    </div >
}

The problem is here: When I move the render elements to an array and then return that array in the render function, it works, but the getDisplay function gets called only when the array is initialized, and isn't called every time, so in this case, clicking doesn't hide the

class Example extends React.Component {
    array = []
    constructor(props) {
        super(props);
        this.state = { show: true }
        //getDisplay is called here instead of getting called on every render/state change.
        this.array.push(
            <div style={{ display: this.getDisplay() }} onClick={() => { console.log('clicked'); this.setState({ show: false }) }}>
                <p>TEST</p>
            </div >
        )
    }
    getDisplay = () => this.state.show ? 'block' : 'none';
    getStyle = () => { { display: this.getDisplay() } }
    render = () => this.array
}

This is a minimal example of the app I'm working on, and I need to keep the array that holds the html element separate and make the render function return it. How can I make the getDisplay get called on every state change in the second code sample? I hope I explained it correctly ,_,

Upvotes: 0

Views: 61

Answers (1)

MynockSpit
MynockSpit

Reputation: 449

The problem is that this.array is static. On construction, you're building the array, and never revisiting it. Instead of building the JSX in the constructor, fill the array with data and then map through it on render.

render: () => this.array.map(item => (
  /* JSX for each item goes here. */
))

Note that b/c this.array isn't state, adding a new item to it won't automatically update it. If you want that behaviour, make sure you a) store it as state (e.g. this.state = { show: true, array: [] }) and b) don't mutate it (i.e. don't use .push, use .concat).

Upvotes: 1

Related Questions