我应该连接子组件以避免重新渲染吗?

时间:2020-07-10 03:35:55

标签: reactjs react-redux

我正在使用Next.js react-redux开发应用程序。

下面的代码是我的应用程序的一部分。

  1. 点击“保存按钮”
  2. 发送动作“ toggleBookmarked”
  3. 在ListItem中更新按钮的文本
    // items

    [
      {id: 1, title: 'title1', is_bookmarked: true},
      {id: 2, title: 'title2', is_bookmarked: false}
    ]


    // components/molecules/ListItem.js

    const ListItem = React.memo(({ item, handleClick }) => {
      return (
        <div>
          <p>{item.title}</p>
          <button onClick={handleClick}>
            {item.is_bookmarked ? 'Unsave' : 'Save'}
          </button>
        </div>
      )
    })

    export default ListItem



    // components/organisms/Results.js

    const Results = ({ items, toggleBookmark }} => {
      return items.map(item => (
        <ListItem
          key={item.id}
          item={item}
          handleClick={() => toggleBookmark(item.id)}
        />
      ))
    }

    const mapStateToProps = (state) => ({
      items: state.classified.items,
    })

    const mapDispatchToProps = (dispatch) => {
      return {
        toggleBookmark: bindActionCreators(toggleBookmark, dispatch)
      }
    }

    export default connect(mapStateToProps, mapDispatchToProps)(Results)



    // action.js

    export const toggleBookmark = (id) => async dispatch => {
      return dispatch({ type: classifiedActionTypes.TOGGLE_BOOKMARK, payload: id })
    }



    // reducer.js

    export default function reducer(state = [], action) {
      switch (action.type) {
        case actionTypes.TOGGLE_BOOKMARK:
          return {
            ...state,
            items: state.items.map(el => el.id === action.payload ? { ...el, is_bookmarked: !el.is_bookmarked } : el)
          }
        default:
          return state
      }
    }

当我打开“突出显示更新”(react devtools)并单击“保存”按钮时,所有ListItem.js都会重新渲染。我只需要单击一下即可重新渲染组件。

我尝试在ListItem中使用{connect},然后将其发送到那里,它起作用了。仅重新单击被单击的ListItem。 但是我只希望将父组件(Results.js)连接到商店。如何仅在不连接到子组件内部存储的情况下重新渲染单击的子组件?

对不起,我的英语不好

其他图像

enter image description here

1 个答案:

答案 0 :(得分:1)

每次ListItem都会重新渲染,因为handleClick每次都会更改。您每次重新Search都会为每个函数创建一个新函数,因此当前使用React.memo并没有实际效果。在这种情况下,应该很容易解决。不必每次都传递新功能,只需向下传递toggleBookmark

    const Search = ({ items, toggleBookmark }} => {
      return items.map(item => (
        <ListItem
          key={item.id}
          item={item}
          handleClick={toggleBookmark}
        />
      ))
    }

然后修改您的ListItem以将其自己的ID传递给它:

    const ListItem = React.memo(({ item, handleClick }) => {
      return (
        <div>
          <p>{item.title}</p>
          <button onClick={() => handleClick(item.id)}>
            {item.is_bookmarked ? 'Unsave' : 'Save'}
          </button>
        </div>
      )
    })

因为要记住ListItem,所以只有itemhandleClick更改时,它才会重新呈现。