我正在使用Redux创建一个测验应用程序,其中包含一个带有一些嵌套字段的表单。我刚刚意识到(我认为),如果我使用子道具,每次按下我的输入框都会触发重新渲染,即像这样设计应用程序:
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嵌套指南”设计的(使用存储类似于关系数据库),可以这样描述。
{
['quizId']: {
questions: ['questionId1'],
['questionId1']:
{ question: 'some question',
answers: ['answerId1', 'answerId2']
},
['answerId1']: { some: 'answer'},
['answerId2']: { some: 'other answer'}
}上面的代码在所有内容都被更新等方面工作,没有错误,但它触发了大量的重新渲染,但只有在我使用合成语法的情况下。如果我将每个组件放在另一个组件中(即不使用props.children),并只发送quizId-key (和其他id-numbers作为道具),它就会像预期的那样工作--没有疯狂的重新渲染。明确地说,当我这样做的时候,它是有效的:
// 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)但是为什么呢?两者之间的区别是什么?我意识到其中一个是作为道具传递给父母的,而不是被渲染为那个父母的孩子,可以这么说,但为什么最终会产生不同的结果呢?它们应该是平等的,但允许更好的语法,这不是重点吗?
编辑:我现在可以验证子道具是不是导致了问题。设置
shouldComponentUpdate(nextProps) {
if (nextProps.children.length === this.props.children.length) {
return false
} else {
return true
}
}修复了问题。然而,这似乎是一个很好的黑盒解决方案,不太确定我现在错过了什么……
发布于 2018-11-13 23:51:10
当您使用render prop模式时,您实际上是在每次呈现组件时声明一个新函数。因此,props.children之间的任何肤浅的比较都将失败。这是该模式的一个众所周知的缺点,您的“黑盒”解决方案是有效的。
发布于 2018-11-13 23:56:55
好的,所以我想通了:
我做了两件坏事:
状态键我让我的顶级组件像这样连接到状态:mapStateToProps(
,
{quizIds.map(quizId => )}
然后我渲染我的孩子数组,注入道具让他们能够单独使用connect,如下所示:
{questions.map((questionId, index) => (
<React.Fragment key={questionId}>
{React.cloneElement(this.props.children, {
index,
questionId,
quizId
})}
</React.Fragment>
))}如果您决定将几个元素放为子元素,那么最后一段代码将无法工作。无论如何,现在看起来更干净了,效果更好了!:D
https://stackoverflow.com/questions/53281471
复制相似问题