【发布时间】:2021-11-14 01:41:51
【问题描述】:
我在 React 中使用函数组件,我有一个名为 'ChallengeItem' 的父组件和一个名为 'ChallengeItem' 的子组件。
'Challenges' 组件调用一个名为 'getAllChallenges' 的操作,该操作从我的数据库中获取所有挑战并通过它们进行映射:
import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getAllChallenges } from '../../actions/challenge';
import Loading from '../layout/Loading';
import ChallengeItem from './ChallengeItem';
const Challenges = ({
getAllChallenges,
challenge: { challenges, loading },
progress,
}) => {
useEffect(() => {
getAllChallenges();
}, [getAllChallenges]);
return loading ? (
<Loading />
) : (
<Fragment>
<h1 className='text-center mt-5'>Course Syllabus</h1>
<div className='row mt-5 mx-5 row-cols-1 row-cols-md-2 row-cols-lg-4 g-4'>
{challenges.map((challenge) => (
<ChallengeItem key={challenge._id} challenge={challenge} />
))}
</div>
</Fragment>
);
};
Challenges.propTypes = {
getAllChallenges: PropTypes.func.isRequired,
challenge: PropTypes.object.isRequired,
progress: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
challenge: state.challenge,
progress: state.auth.user.progress,
});
export default connect(mapStateToProps, { getAllChallenges })(Challenges);
'ChallengeItem' 组件返回一个动态显示个人挑战信息的 Fragment:
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
const ChallengeItem = ({
auth,
user: { progress },
challenge: { _id, section_name, section_no, challenge_no, challenge_name },
}) => (
<Fragment>
<div className='col'>
<div className='card challengeCard'>
<div className='card-body'>
<h5 className='card-title'>
Section {section_no}, Challenge {challenge_no}
</h5>
<p className='card-text'>
{section_name}- {challenge_name}
</p>
{isChallengeUnlocked(_id, progress) ? (
<Link
to={`/challenge/${_id}`}
className='btn btn-secondary pinkBtn'
>
Unlocked <i className='fas fa-lock-open'></i>
</Link>
) : (
<button className='btn btn-secondary pinkBtn' disabled>
Locked <i className='fas fa-lock'></i>
</button>
)}
</div>
</div>
</div>
</Fragment>
);
ChallengeItem.propTypes = {
challenge: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
auth: state.auth,
user: state.auth.user,
});
export default connect(mapStateToProps)(ChallengeItem);
function isChallengeUnlocked(_id, progress) {
for (const value of progress) {
if (value.challenge === _id) {
return true;
}
}
return false;
}
'ChallengeItem' 组件中还有一个函数,它根据用户的进度确定他们是否已解锁特定挑战。
如果他们解锁了挑战,它将显示出来,并且用户可以点击链接导航到该挑战。
如果他们未解锁了挑战,则会显示该挑战,但此挑战的按钮将禁用,用户将无法点击它。
我遇到的问题是,当用户新解锁挑战并且用户导航到挑战页面以查看所有锁定/解锁的挑战时,新解锁的挑战在页面上显示为锁定且仅当页面刷新时,新解锁的挑战会显示为解锁状态。
当子组件更新时如何获得重新渲染的挑战?
我在网上搜索了一个答案,似乎很多人都在说为子组件设置一个密钥以便它重新渲染,但我已经在这样做了。我不确定是什么问题,也许这是一个单独的问题。
非常感谢您在此阶段提供的任何帮助,谢谢!
编辑:
// getAllChallenges action
export const getAllChallenges = () => async (dispatch) => {
try {
const res = await axios.get(`/api/challenge/all`);
dispatch({
type: GET_CHALLENGES,
payload: res.data,
});
} catch (err) {
dispatch({
type: CHALLENGE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};
// UPDATE_PROGRESS reducer
case UPDATE_PROGRESS:
return {
...state,
user: {
...state.user,
progress: payload,
},
loading: false,
};
【问题讨论】:
-
目前,您只能在开头抓取。您需要将进度传递给函数,然后将其添加到依赖数组中。基本上,如果进度更改触发获取。
-
我尝试将 Challenge 组件中的 useEffect 更改为:useEffect(() => { getAllChallenges(); }, [progress]);当进度状态发生变化时尝试加载所有挑战,但它仍然给我同样的问题
-
getAllChallenges操作看起来如何? -
嗨 Seshkebab,我删除了我的答案,对此感到抱歉。我错过了你正在使用 redux。顺便说一句,当您发现挑战已解锁时,您是否可以不发送操作。这将更新存储在 redux 存储中的
challenges? -
@merko 我已经更新了我的答案,附带了 getAllChallenges 操作
标签: javascript reactjs react-redux react-functional-component