У меня есть компонент, который возвращает объект с именем Progress
, внутри которого находится массив с именем Results
. В этом массиве есть объекты с различными свойствами, одно из которых называется total
{
Progress: {
count: 100,
results: [
{total: 4, ...},
{total: 10, ...},
...
]
}
}
Компонент Dashboard
получает данные из состояния и сопоставляет их со свойством Progress.
export class Dashboard extends Component {
static propTypes = {
progress: PropTypes.object.isRequired,
getProgress: PropTypes.func.isRequired,
totalResults: PropTypes.number.isRequired
}
componentDidMount() {
this.props.getProgress()
}
...
}
const selectProgress = state => state.progressReducer.progress
const mapStateToProps = state => ({
progress: selectProgress(state),
})
export default connect(mapStateToProps, { getProgress })(Dashboard)
Проблема, с которой я столкнулся сейчас, заключается в том, как добавить новое свойство, полученное из хода выполнения?
Я понимаю, что должен использовать селектор, но не могу понять, где и как это сделать.
Например, я знаю, что могу сделать что-то тривиальное (и бессмысленное), например:
const mapStateToProps = state => ({
progress: selectProgress(state),
count: selectProgress(state).count
})
, которое добавляет другое свойство count
к компоненту (да, оно просто дублирует свойство внутри прогресса, поэтому почему это бессмысленно).
Что мне нужно сделать, это примерно так:
const mapStateToProps = state => ({
progress: selectProgress(state),
resultsTotal: <loop through the results array and sum the property total>
})
1 - что я пробовал
I попробовал это, хотя я понимаю, что это не так. Надеюсь, это иллюстрирует то, что я пытаюсь сделать - ПОСЛЕ того, как у меня есть прогресс, передайте его какой-то функции для вычисления суммы и верните ее как свойство компоненту:
const selectResults = progress => {
progress.results.reduce((acc, result) => {
acc + result.total
}, 0)
}
const mapStateToProps = state => ({
progress: selectProgress(state),
totalResults: selectResults(progress)
})
2 - То, что я пробовал
Я думал, что это сработало бы, в основном позволяя функции вызова представления рендеринга в точке, необходимой в JSX:
export class Dashboard extends Component {
static propTypes = {
progress: PropTypes.object.isRequired,
getProgress: PropTypes.func.isRequired,
}
componentDidMount() {
this.props.getProgress()
}
totalResults() {
if (this.props.progress.results)
return this.props.progress.results.reduce((acc, result) => {
acc + result.total
}, 0)
}
render() {
...
<SummaryCard title='Students' value={this.totalResults()} />
...
}
}
Я сейчас интересно, почему это не сработало - мне пришлось добавить следующую строку:
if (this.props.progress.results)
, поскольку при выполнении этой функции прогресс, конечно, пустой (ie Я полагаю, потому что он выполняется при первом монтировании компонента, и магазин еще не вернул данные).