【问题标题】:React child component only updates on refreshReact 子组件仅在刷新时更新
【发布时间】: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


【解决方案1】:

由于ChallengeItem 是一个 Redux 连接组件,它依赖于 Redux 状态,因此您需要设置 pure: false in the connect() options

export default connect(mapStateToProps, null, null, {pure: false})(ChallengeItem);

【讨论】:

  • 谢谢,我试过了,但对我不起作用
猜你喜欢
  • 2021-05-08
  • 1970-01-01
  • 2021-05-29
  • 2018-10-09
  • 2020-08-08
  • 2013-03-02
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
相关资源
最近更新 更多