Skip to content

Instantly share code, notes, and snippets.

@typoerr
Last active June 2, 2017 11:13
Show Gist options
  • Select an option

  • Save typoerr/a4e7cfdac6c069aa9ba616fb1d57fd39 to your computer and use it in GitHub Desktop.

Select an option

Save typoerr/a4e7cfdac6c069aa9ba616fb1d57fd39 to your computer and use it in GitHub Desktop.
import { Component } from 'preact';
export interface Props {
cond: boolean | ((prevProps: any) => boolean);
[K: string]: any;
}
export default class ShouldChildrenUpdate extends Component<Props, void> {
prevProps: any = this.props;
shouldComponentUpdate(nextProps: Props) {
const { cond, ...rest } = nextProps;
const result = (typeof cond === 'function') ? cond(this.prevProps) : cond;
this.prevProps = rest;
return result;
}
render(props: any) {
return props.children && props.children[0] || null;
}
}
@typoerr

typoerr commented May 30, 2017

Copy link
Copy Markdown
Author

example

import { h, Component } from 'preact';
import ShouldChildrenUpdate from '@components/functional/ShouldChildrenUpdate';

interface S {
    count: number;
}

function shouldUpdate(this: TimerCounter, p: S) {
    if (this.state.count < 10) return false;
    if (p.count === this.state.count) return false;
    return true;
}

export default class TimerCounter extends Component<any, S> {
    state = {
        count: 0
    };

    onClick = () => this.setState({ count: this.state.count + 1 });

    render() {
        return (
            <div>
                <h1>parent scope</h1>
                <div>
                    <span>{this.state.count}</span>
                    <button onClick={this.onClick}>inc</button>
                </div>
                <ShouldChildrenUpdate {...this.state} cond={shouldUpdate.bind(this)} >
                    <Child count={this.state.count}>
                        {this.state.count}
                    </Child>
                </ShouldChildrenUpdate>
            </div>
        );
    }
}

export class Child extends Component<{ count: number }, any> {
    state = {
        count: 0
    };
    render() {
        return (
            <div>
                <h2>child scope</h2>
                <ul>
                    <li>state: {this.state.count}</li>
                    <li>props: {this.props.count}</li>
                    <li>children: {this.props.children}</li>
                </ul>
            </div>
        );
    }
}

@typoerr

typoerr commented May 30, 2017

Copy link
Copy Markdown
Author

注意事項

<ShouldChildrenUpdate {...this.state} cond={shouldUpdate.bind(this)} >
    <Child count={this.state.count}>
        {[1, 2, 3].map(x => <div>{x}</div>)} // (1)
    </Child>
</ShouldChildrenUpdate>

(1)の計算は親コンポーネントスコープなので、updateは走らないが計算は親のrender毎に実行される

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment