如何防止子组件重新渲染? [英] How to prevent children component from rerendering?

查看:85
本文介绍了如何防止子组件重新渲染?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的搜索栏组件更改了布局组件的状态.因此,布局组件会触发其所有子组件的重新渲染.我试图实现 React.memo(),但它没有帮助我.请纠正我.提前致谢!

布局组件:

export default class Layout extends Component {状态 = {城市名: "",日期: "",图标: "",};searchbarSubmitHandler = e =>{const 城市名称 =e.target.children[0].firstChild.children[0].value;this.setState({城市名称:城市名称});console.log(this.state.cityName);e.preventDefault();};searchbarChangeHandler = e =>{this.setState({城市名称:e.target.value});};使成为() {返回 (<div><搜索栏提交={this.searchbarSubmitHandler}change={this.searchbarChangeHandler}/><开关><路线精确的路径=/"组件={() =><当前天气图标={this.state.icon}/>}/><路线路径="/24 小时天气"组件={每小时天气}/></开关>

);}}

搜索栏组件:

const searchbar = props =>{返回 (<div className="搜索栏"><form onSubmit={props.submit}><div className="输入"><div className="inputTextWrapper"><输入类名=输入文本"类型=文本"placeholder="城市名称..."onChange={props.change}/>

<输入类名=输入提交"类型=提交"值=搜索"/>

</表单>

);};导出默认搜索栏;

我不想重新渲染的 CurrentWeather 组件:

const currentWeather = props =>{返回 (<div className="容器"><h3>英国伦敦</h3>

);};const areEqual = (prevProps, nextProps) =>prevProps === nextProps;导出默认 React.memo(currentWeather, areEqual);

解决方案

问题是

<路由精确的路径=/"组件={() =><CurrentWeather icon={this.state.icon}/>}/>

component 的工作方式是路由器使用 React.createElement 从给定的组件创建一个新的 React 元素.卸载现有组件并安装新组件,而不是仅仅更新现有组件组件"

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Route.md#component

如果你把它改成render,你不会得到这个效果,也不会重新创建这个组件.

<路由精确的路径=/"渲染={() =><CurrentWeather icon={this.state.icon}/>}/>

https://codesandbox.io/s/restless-hill-2ykhq显示这个工作

My searchbar component changes state of Layout component. Therefore, Layout component triggres rerendering of all its childs components. I tried to implement React.memo(), but it didn't help me. Please correct me. Thank you in advance!

Layout component:

export default class Layout extends Component {
    state = {
        cityName: "",
        date: "",
        icon: "",
    };

    searchbarSubmitHandler = e => {
        const cityName =
            e.target.children[0].firstChild.children[0].value;
        this.setState({
            cityName: cityName
        });
        console.log(this.state.cityName);
        e.preventDefault();
    };

    searchbarChangeHandler = e => {
        this.setState({
            cityName: e.target.value
        });
    };
    render() {
        return (
            <div>
                <Searchbar
                    submit={this.searchbarSubmitHandler}
                    change={this.searchbarChangeHandler}
                />
                <Switch>
                    <Route
                        exact
                        path="/"
                        component={() =>
                            <CurrentWeather icon={this.state.icon} />
                        }
                    />
                    <Route
                        path="/24h-weather"
                        component={HourlyWeather}
                    />
                </Switch>
            </div>
        );
    }
}

searchbar component:

const searchbar = props => {
    return (
        <div className="searchbar">
            <form onSubmit={props.submit}>
                <div className="inputs">
                    <div className="inputTextWrapper">
                        <input
                            className="inputText"
                            type="text"
                            placeholder="City name..."
                            onChange={props.change}
                        />
                    </div>

                    <input
                        className="inputSubmit"
                        type="submit"
                        value="Search"
                    />
                </div>
            </form>
        </div>
    );
};

export default searchbar;

CurrentWeather component which I want to not rerender:

const currentWeather = props => {
    return (
        <div className="container">
            <h3>London, UK</h3>
            <img
              src={`http://openweathermap.org/img/wn/${props.icon}.png`}
              alt="weather icon"
            />
        </div>
    );
};

const areEqual = (prevProps, nextProps) => prevProps === nextProps;

export default React.memo(currentWeather, areEqual);

解决方案

The issue is

<Route
    exact
    path="/"
    component={() => <CurrentWeather icon={this.state.icon} />}
    />

The way that component works is "router uses React.createElement to create a new React element from the given component. The existing component is unmounted and the new component is mounted instead of just updating the existing component"

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Route.md#component

If you change this to render, you will not get this effect, and it won't recreate this component.

<Route
    exact
    path="/"
    render={() => <CurrentWeather icon={this.state.icon} />}
    />

https://codesandbox.io/s/restless-hill-2ykhq to show this working

这篇关于如何防止子组件重新渲染?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆