如何防止子组件重新呈现?

时间:2019-11-13 19:58:04

标签: javascript reactjs optimization react-hooks

我的搜索栏组件更改了布局组件的状态。因此,布局组件触发所有子组件的重新呈现。我尝试实现React.memo(),但并没有帮助我。请纠正我。预先谢谢你!

布局组件:

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>
        );
    }
}

搜索栏组件:

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组件:

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);

3 个答案:

答案 0 :(得分:0)

问题可能是传递给props的{​​{1}}参数是一个对象,因此您的CurrentWeather第二个参数(React.memo)检查对象是否相等。
在不同的渲染过程中传递的两个prop对象不会严格相等,甚至会变得很浅,因为它们引用内存中的不同位置-因此,areEqual始终返回false。

您可能希望将prevProps === nextProps重构为类似的内容:

areEqual

假设const areEqual = (prevProps, nextProps) => prevProps.icon === nextProps.icon; 道具是传递给icon的道具中唯一更改或我们关心的道具。

答案 1 :(得分:0)

问题是

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

component的工作方式是“路由器使用React.createElement从给定组件中创建新的React元素。卸载现有组件并安装新组件,而不仅仅是更新现有组件” < / p>

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

如果将其更改为render,将不会获得此效果,并且不会重新创建此组件。

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

https://codesandbox.io/s/restless-hill-2ykhq来显示此功能

答案 2 :(得分:0)

我建议不要将图标存储在父组件的状态中,而是存储在子组件中,因为这样可以减少依赖性。如果您需要从父母那里进行设置,请查看udi表格上方的答案