React 中,我们可以创建独立的 component 来封装特定的功能。因此,可以根据不同的程序的 state 选择性的做部分渲染。

和 JavaScript 的相同,React 中也可以使用 conditions 语法来选择性的渲染内容。如使用 if 或 conditional operator 来根据不同 state 状态创建不同 elements 然后让 React 更新 UI 来匹配 DOM。

考虑下面两个 components:

const UserGreeting = (props) => {
    return <h1>welcome back</h1>
}

const GuestGreeting = (props) => {
    return <h1>please sign up</h1>
}

然后我们创建一个 Greeting component 来根据是否有用户登陆来显示以上两个中的一个:

const Greeting = (props) => {
    let isLoggedIn = props.isLoggedIn;
    if (isLoggedIn)
        return <UserGreeting />;
    else
        return <GuestGreeting />;
}

ReactDOM.render(
    <Greeting isLoggedIn={true} />,
    document.getElementById('root')
);

以上示例会根据 isLoggedIn 属性的值来渲染不同的内容。

elements 变量

可以使用变量存储 elements,这样可以方便的根据情况 render 部分的 component 而不需要改变输出的指令内容。

考虑下面两个 component 表示 login 和 logout:

const LoginButton = (props) => {
    return (
        <button onClick={props.onClick}>
            login
        </button>
    );
}

const LogoutButton = (props) => {
    return (
        <button onClick={props.onClick}>
            logout
        </button>
    );
}

然后我们创建 LoginControl component,它将根据当前情况渲染 login 或 logout button 以及之前创建的 Greeting element:

class LoginControl extends React.Component {
    constructor(props) {
        super(props);
        this.handleLoginClick = this.handleLoginClick.bind(this);
        this.handleLogoutClick = this.handleLogoutClick.bind(this);
        this.state = {isLoggedIn: false};
    }

    handleLoginClick() {
        this.setState({isLoggedIn: true});
    }

    handleLogoutClick() {
        this.setState({isLoggedIn: false});
    }

    render() {
        let isLoggedIn = this.state.isLoggedIn;
        let button;
        if (isLoggedIn)
            button = <LogoutButton onClick={this.handleLogoutClick} />
        else
            button = <LoginButton onClick={this.handleLoginClick} />

        return (
            <div>
                <Greeting isLoggedIn={isLoggedIn} />
                {button}
            </div>
        );
    }

}

ReactDOM.render(
    <LoginControl />,
    document.getElementById('root')
);

inline condition 单语句判断

使用 element 变量以及使用 if 语句根据条件渲染 component 是一种很好的方法。但是有时候可以使用简化语法。下面接收几种 inline condition 语法。

inline if with && operator

在 JSX 可以通过使用大括号{}来嵌入 JavaScript 表达式,包括逻辑符号:&&,在根据条件判断是否包含一个 element 时很有用。

请看下面示例:

const InlineCom = (props) => {
    return(
        <div>
            <h1>hello world</h1>
            {props.count > 10 &&
                <h2>count is: {props.count}</h2>
            }
        </div>
    );
}

ReactDOM.render(
    <InlineCom count={20} />,
    document.getElementById('root')
);

如果 props.count > 10 满足条件则后面的 element 就会成为 component 一部分。

在 JavaScript 中,true && expression 将会评估为 expression,而 false && expression 将会评估为 false。因此当 condition 为 true 时,&& 后的 element 将会输出,否则 React 将会忽略它。

inline condition operator

另一种根据情况通过 inline 单行判断来渲染 element 就是使用 JavaScript conditional operator:condition ? true : false

给 LoginControl 的返回添加如下:

        return (
            <div>
                the user is <b>{isLoggedIn ? 'currenty' : 'not'}</b> logged in.
                <Greeting isLoggedIn={isLoggedIn} />
                {button}
            </div>
        );

通过 inline conditional operator 来输出不同的信息。

也可以在较长的表达式中使用,例如可以将示例中 button 部分在 render 中这样处理:

        return (
            <div>
                the user is <b>{isLoggedIn ? 'currenty' : 'not'}</b> logged in.
                <Greeting isLoggedIn={isLoggedIn} />
                {button}
                {isLoggedIn 
                    ? <LogoutButton onClick={this.handleLogoutClick} />
                    : <LoginButton onClick={this.handleLoginClick} />
                }
            </div>
        );

使用中根据实际情况选择最合适的方式处理 condition,最终目的是为了使结构更加清晰,代码易读。注意如果判断过复杂就需要考虑拆解 component 为多个个体了。

阻止 component 渲染

某些情况下我们可能需要将一个 component 隐藏起来,即使它在别的 component 中已经渲染了。可以通过 return null 来代替它的输出。

下面示例中 WarningBanner 会根据 warn 属性的值来选择性渲染:

const React = require('react')
const ReactDOM = require('react-dom')

const WarningBanner = (props) => {
    if (!props.warn) {
        return null;
    }
    return (
        <div className='warning'>
            warning!
        </div>
    );
}

class Page extends React.Component {
    constructor(props) {
        super(props);
        this.state = {showWarning: true};
        this.handelToggleClick = this.handelToggleClick.bind(this);
    }
    handelToggleClick() {
        this.setState({showWarning: !this.state.showWarning});
    }

    render() {
        return (
            <div>
                <WarningBanner warn={this.state.showWarning} />
                <button onClick={this.handelToggleClick}>
                    {this.state.showWarning ? 'hide' : 'show'}
                </button>
            </div>
        );
    }
}

ReactDOM.render(
    <Page />,
    document.getElementById('root')
);

render method 中 return null 不会影响到 component 的 lifecycle method。例如每次更新 componentDidUpdate 依然会被自动调用。

标签: none

添加新评论