首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用map和redux时,子道具触发重新渲染

使用map和redux时,子道具触发重新渲染
EN

Stack Overflow用户
提问于 2018-11-13 20:54:16
回答 2查看 131关注 0票数 1

我正在使用Redux创建一个测验应用程序,其中包含一个带有一些嵌套字段的表单。我刚刚意识到(我认为),如果我使用子道具,每次按下我的输入框都会触发重新渲染,即像这样设计应用程序:

代码语言:javascript
复制
const keys = Object.keys(state)

<QuizContainer>
  {keys.map(key => 
    <QuizForm key={key}>
        {state[key].questions.map(({ questionId }) => 
           <Question key={questionId} questionId={questionId}>
               {state[key]questions[questionId].answers.map(({ answerId })=>
                   <Answer answerId={answerId} key={answerId} />
               )}
           </Question>
        )}
    </QuizForm>
  )}
</QuizContainer>

QuizContainer通过mapStateToProps和mapDispatchToProps连接到redux,并输出一个数组数组,其中所有数组都包含对象。存储结构是根据Dan Abramov的“redux嵌套指南”设计的(使用存储类似于关系数据库),可以这样描述。

代码语言:javascript
复制
{
    ['quizId']: {
        questions: ['questionId1'],
        ['questionId1']:
            { question: 'some question', 
                answers: ['answerId1', 'answerId2']
            },
        ['answerId1']: { some: 'answer'},
        ['answerId2']: { some: 'other answer'}
 }

上面的代码在所有内容都被更新等方面工作,没有错误,但它触发了大量的重新渲染,但只有在我使用合成语法的情况下。如果我将每个组件放在另一个组件中(即不使用props.children),并只发送quizId-key (和其他id-numbers作为道具),它就会像预期的那样工作--没有疯狂的重新渲染。明确地说,当我这样做的时候,它是有效的:

代码语言:javascript
复制
// quizId and questionId being passed from parent component's map-function (QuizForm)

const Question ({ answers }) => 
    <>
      {answers.map(({ answerId }) => 
        <Answer key={answerId} answerId={answerId} />
      )}
    </>

const mapStateToProps = (state, { questionId, quizId }) => ({
    answers: state[quizId][questionId].answers
})

export default connect(mapStateToProps)(Question)

但是为什么呢?两者之间的区别是什么?我意识到其中一个是作为道具传递给父母的,而不是被渲染为那个父母的孩子,可以这么说,但为什么最终会产生不同的结果呢?它们应该是平等的,但允许更好的语法,这不是重点吗?

编辑:我现在可以验证子道具是不是导致了问题。设置

代码语言:javascript
复制
shouldComponentUpdate(nextProps) {
    if (nextProps.children.length === this.props.children.length) {
       return false
       } else {
       return true
    }
}

修复了问题。然而,这似乎是一个很好的黑盒解决方案,不太确定我现在错过了什么……

EN

回答 2

Stack Overflow用户

发布于 2018-11-13 23:51:10

当您使用render prop模式时,您实际上是在每次呈现组件时声明一个新函数。因此,props.children之间的任何肤浅的比较都将失败。这是该模式的一个众所周知的缺点,您的“黑盒”解决方案是有效的。

票数 0
EN

Stack Overflow用户

发布于 2018-11-13 23:56:55

好的,所以我想通了:

我做了两件坏事:

状态键我让我的顶级组件像这样连接到状态:mapStateToProps(

  • ) => ({mapStateToProps:Object.keys(=>)})。我以为对象函数会返回一个“静态”数组,并阻止我监听整个状态,但事实证明我错了。显然(现在对我来说),每次我更改状态时,我都会得到一个新的数组(但具有相同的条目)。我现在把它们存储在一个完全独立的属性上,叫做quizIds,

  • ,我把我的映射函数放在了一个不好的地方。我现在继续像这样呈现QuizContainer:

{quizIds.map(quizId => )}

然后我渲染我的孩子数组,注入道具让他们能够单独使用connect,如下所示:

代码语言:javascript
复制
    {questions.map((questionId, index) => (
      <React.Fragment key={questionId}>
        {React.cloneElement(this.props.children, {
          index,
          questionId,
          quizId
        })}
      </React.Fragment>
    ))}

如果您决定将几个元素放为子元素,那么最后一段代码将无法工作。无论如何,现在看起来更干净了,效果更好了!:D

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53281471

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档