Liondancer
Liondancer

Reputation: 16479

Setting state with methods passed into dumb components

Within my smart component, I have methods that I want to use to set state of my smart component. When a user interacts with the dumb component, the methods passed down from the smart component will be triggered and that to change the state of my smart component

In my code below, I want my setHighlight to change my state.highlight to a string onClick. clearHighlight has the same functionality except it sets this.state.highlight = null. Once this state has been set, this.state.highlight is passed to my PrettyPrintPageSource in order to perform the logic in highlightTag.

My code is currently showing these errors:

warning.js:44Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the HomePage component.warning @ warning.js:44

warning.js:44Warning: Failed prop type: Required prop `setHighlightTag` was not specified in `TagSummary`.
    in TagSummary (created by HomePage)
    in HomePage (created by Connect(HomePage))
    in Connect(HomePage) (created by RouterContext)
    in div (created by App)
    in MuiThemeProvider (created by App)
    in App (created by RouterContext)
    in RouterContext (created by Router)
    in Router
    in Providerwarning @ warning.js:44
warning.js:44Warning: Failed prop type: Required prop `clearHighlight` was not specified in `TagSummary`.
    in TagSummary (created by HomePage)
    in HomePage (created by Connect(HomePage))
    in Connect(HomePage) (created by RouterContext)
    in div (created by App)
    in MuiThemeProvider (created by App)
    in App (created by RouterContext)
    in RouterContext (created by Router)
    in Router
    in Provider

Here is my code:

class HomePage extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            highlight: null
        };
        this.getPageSource = this.getPageSource.bind(this);
        this.updateURLstate = this.updateURLstate.bind(this);
        this.highlightTag = this.highlightTag.bind(this);
        this.clearHighlight = this.clearHighlight(this);
        this.setHighlightTag = this.setHighlightTag(this);
    }

    getPageSource(event) {
        event.preventDefault();
        this.props.actions.getPageSource(this.state.url);
    }

    updateURLstate(event) {
        const url = event.target.value;
        this.setState({
            url
        });
    }

    setHighlightTag(tag) {
        this.setState({
            highlight: tag
        });
    }

    highlightTag(pageSource, tag) {
        if (tag) {
            let re = new RegExp(tag, "g");
            pageSource.replace(re, "<span class='red'>"+ tag +"</span>")
        }
    }

    clearHighlight() {
        this.setState({
            highlight: null
        });
    }

    render() {
        return (
            <div>
                <UrlForm
                    onSearch={ this.getPageSource }
                    onChange={ this.updateURLstate }
                />

                <PrettyPrintPageSource
                    badUrl={ this.props.payload.error }
                    prettyPrintPageSource={ this.props.payload.prettySource }
                    highlighter={ this.highlightTag }
                    tag={ this.state.highlight }
                />
                <TagSummary
                    tags={ this.props.payload.tagData }
                    setHighlightTag={ this.setHighlightTag }
                    clearHighlight={ this.clearHighlight }
                />
            </div>
        );
    }
}

TagSummary dumb Component:

const TagSummary = ({ tags, setHighlightTag, clearHighlight }) => {
    if (!tags) {
        return <div />;
    }
    return (
        <div>
            {Object.keys(tags).map((tag) => {
                return (
                    <div key={ tag }>
                        <button type="button" onClick={ setHighlightTag.bind(this, tag) }>
                            <pre>&lt;{ tag }&gt;</pre>
                        </button>
                        <p>{ tags[tag] }</p>
                    </div>

                );
            })}
            <button onClick={ clearHighlight }>Clear</button>
        </div>
    );
};

PrettyPrintPageSource dumb Component:

const PrettyPrintPageSource = ({ prettyPrintPageSource, badUrl, highlighter, tag }) => {
    if (badUrl) {
        return (
            <div>
                Bad URL!
            </div>
        );
    } else {

        let processedPageSource = highlighter.bind(this, prettyPrintPageSource, tag);

        return (
            <pre>
                { processedPageSource }
            </pre>
        );
    }
};

Upvotes: 0

Views: 247

Answers (1)

Phi Nguyen
Phi Nguyen

Reputation: 3056

You forgot bind clearHighlight and setHighlightTag methods. Change those lines :

  constructor(){
   ....
   this.clearHighlight = this.clearHighlight.bind(this);
   this.setHighlightTag = this.setHighlightTag.bind(this);
   }

Upvotes: 2

Related Questions