Я использую 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 и выдает массив массивов, в которых все объекты содержат внутри себя. Структура магазина разработана в соответствии с «Руководством по вложениям редуксов» Дана Абрамова (с использованием типа магазина, подобного реляционной базе данных) и может быть описана следующим образом.
{
['quizId']: {
questions: ['questionId1'],
['questionId1']:
{ question: 'some question',
answers: ['answerId1', 'answerId2']
},
['answerId1']: { some: 'answer'},
['answerId2']: { some: 'other answer'}
}
Приведенный выше код работает с точки зрения всего, что обновляется и т. Д. И т. Д., Без ошибок, но он вызывает безумное количество повторных рендеров, но ТОЛЬКО если я использую синтаксис композиции. Если я помещаю каждый компонент в другой (т.е. не использую props.children) и просто отправляю ключ quizId (и другие id-номера в качестве реквизитов), он работает как положено - без сумасшедшего повторного рендеринга. Чтобы быть кристально чистым, это работает, когда я делаю что-то вроде этого:
// 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
}
}
исправляет проблему. Тем не менее, похоже, что это довольно «черный ящик», не совсем уверенный в том, что я упускаю прямо сейчас ...