仅用反应钩子渲染一个孩子

时间:2019-06-03 07:33:08

标签: reactjs react-hooks

const {useRef, useState} = React;

function List(){
  const renderCount = useRef(0);
  console.log('<List /> is rendered', ++renderCount.current);
  const [isClicked, setIsClicked] = useState(false);
  const toggle = () => setIsClicked(!isClicked)
  return (
    <div>
      <ButtonA onClick={toggle} isClicked={isClicked} />
      <ButtonB />
    </div>
  )
}

function ButtonA(props){
  const renderCount = useRef(0);
  console.log('<ButtonA /> is rendered', ++renderCount.current);

  return (<button onClick={props.onClick} className={`${props.isClicked ? 'true':'false'}`} >Button A</button>);
}

function ButtonB(){
  const renderCount = useRef(0);
  console.log('<ButtonB /> is rendered', ++renderCount.current);
  
  return (<button>Button B </button>);
}


ReactDOM.render(
  <List />, document.getElementById('root')
)
button.true{
  background-color: red;
}

button.false{
  background-color: blue;
  
  }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

这是示例代码。

当我单击<ButtonA />时,我希望重新渲染<List /><Button A/>,但是<ButtonB />也被重新渲染。

当我单击<ButtonB />时,我想阻止重新渲染<ButtonA />

我该如何实现?

3 个答案:

答案 0 :(得分:2)

对于功能组件,您可以使用React.memo来具有与shouldComponentUpdate相同的功能

const {useRef, useState} = React;

function List(){
  const renderCount = useRef(0);
  console.log('<List /> is rendered', ++renderCount.current);
  const [isClicked, setIsClicked] = useState(false);
  const toggle = () => setIsClicked(!isClicked)
  return (
    <div>
      <ButtonA onClick={toggle} isClicked={isClicked} />
      <ButtonB />
    </div>
  )
}

function ButtonA(props){
  const renderCount = useRef(0);
  console.log('<ButtonA /> is rendered', ++renderCount.current);

  return (<button onClick={props.onClick} className={`${props.isClicked ? 'true':'false'}`} >Button A</button>);
}

const ButtonB = React.memo(() => {
  const renderCount = useRef(0);
  console.log('<ButtonB /> is rendered', ++renderCount.current);
  
  return (<button>Button B </button>);
})


ReactDOM.render(
  <List />, document.getElementById('root')
)
button.true{
  background-color: red;
}

button.false{
  background-color: blue;
  
  }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

优化功能组件以使React可以将其视为纯组件,不一定需要将该组件转换为类组件。

如果您已经熟悉了recompose软件包,那么您会知道它提供了大量的高阶组件,这在处理功能组件时非常有用。

recompose包导出一个{pure}高阶组件,该组件试图通过阻止对组件的更新(除非道具已更改)来优化React组件,除非使用propeEqual()来测试更改。

使用纯的高阶组件,我们的功能组件可以包装如下:

import React from 'react';
import { pure } from 'recompose';

function ButtonB() {
  const renderCount = useRef(0);
  console.log('<ButtonB /> is rendered', ++renderCount.current);

  return (<button>Button B </button>);
}
// Wrap component using the `pure` HOC from recompose
export default pure(ButtonB);

答案 2 :(得分:0)

默认情况下,如果父级的状态发生更改,则会重新渲染父级的所有子级。此更改是否对孩子有直接影响都没有关系。 但是,您可以使用shouldComponentUpdate生命周期方法显式禁用特定组件的重新渲染。

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
class Button extends React.Component {
  shouldComponentUpdate(){
    return !this.props.shouldNotUpdate;
  }
  
  render(){
    const { id, onClick } = this.props;
    console.log(`button ${this.props.id} rendered`)
    return <button onClick={onClick}>{`Button ${id}`}</button>
  }
}

class App extends React.Component {
  state = { clicked: 0 }
  
  handleClick = () => this.setState(({clicked}) => ({clicked: clicked + 1}))
  
  render(){
    return (
      <div>
        {this.state.clicked}<br />
        <Button id="1" onClick={this.handleClick} />
        <Button id="2" shouldNotUpdate />
      </div>
    )
  }
}

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