chore: convert frontend to functional component (#57395)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Sem Bauke
2024-12-03 13:31:11 +01:00
committed by GitHub
parent 0913e81a15
commit 15dcf72005

View File

@@ -1,7 +1,7 @@
import { graphql } from 'gatsby';
import React, { Component } from 'react';
import React, { useEffect, useRef } from 'react';
import Helmet from 'react-helmet';
import type { TFunction } from 'i18next';
import { type TFunction } from 'i18next';
import { withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
@@ -67,33 +67,32 @@ interface ProjectProps {
updateSolutionFormValues: () => void;
}
// Component
class Project extends Component<ProjectProps> {
static displayName: string;
private container: React.RefObject<HTMLElement> = React.createRef();
const ShowFrontEndProject = (props: ProjectProps) => {
const handleSubmit = ({
showCompletionModal
}: {
showCompletionModal: boolean;
}): void => {
if (showCompletionModal) {
props.openCompletionModal();
}
};
constructor(props: ProjectProps) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
const container = useRef<HTMLElement>(null);
useEffect(() => {
const {
challengeMounted,
data: {
challengeNode: {
challenge: {
fields: { tests },
title,
challengeType,
helpCategory
}
challenge: { fields, title, challengeType, helpCategory }
}
},
pageContext: { challengeMeta },
initTests,
updateChallengeMeta
} = this.props;
initTests(tests);
} = props;
initTests(fields.tests);
updateChallengeMeta({
...challengeMeta,
title,
@@ -101,131 +100,89 @@ class Project extends Component<ProjectProps> {
helpCategory
});
challengeMounted(challengeMeta.id);
this.container.current?.focus();
}
container.current?.focus();
// This effect should be run once on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
componentDidUpdate(prevProps: ProjectProps): void {
const {
data: {
challengeNode: {
challenge: { title: prevTitle }
const {
data: {
challengeNode: {
challenge: {
challengeType,
fields: { blockName },
forumTopicId,
title,
description,
instructions,
superBlock,
block,
translationPending
}
}
} = prevProps;
const {
challengeMounted,
data: {
challengeNode: {
challenge: { title: currentTitle, challengeType, helpCategory }
}
},
pageContext: { challengeMeta },
updateChallengeMeta
} = this.props;
if (prevTitle !== currentTitle) {
updateChallengeMeta({
...challengeMeta,
title: currentTitle,
challengeType,
helpCategory
});
challengeMounted(challengeMeta.id);
}
}
},
isChallengeCompleted,
pageContext: {
challengeMeta: { nextChallengePath, prevChallengePath }
},
t,
updateSolutionFormValues
} = props;
handleSubmit({
showCompletionModal
}: {
showCompletionModal: boolean;
}): void {
if (showCompletionModal) {
this.props.openCompletionModal();
}
}
const blockNameTitle = `${t(
`intro:${superBlock}.blocks.${block}.title`
)} - ${title}`;
render() {
const {
data: {
challengeNode: {
challenge: {
challengeType,
fields: { blockName },
forumTopicId,
title,
description,
instructions,
superBlock,
block,
translationPending
}
}
},
isChallengeCompleted,
pageContext: {
challengeMeta: { nextChallengePath, prevChallengePath }
},
t,
updateSolutionFormValues
} = this.props;
const blockNameTitle = `${t(
`intro:${superBlock}.blocks.${block}.title`
)} - ${title}`;
return (
<Hotkeys
containerRef={this.container}
nextChallengePath={nextChallengePath}
prevChallengePath={prevChallengePath}
>
<LearnLayout>
<Helmet
title={`${blockNameTitle} | ${t('learn.learn')} | freeCodeCamp.org`}
/>
<Container>
<Row>
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
<Spacer size='m' />
<ChallengeTitle
isCompleted={isChallengeCompleted}
translationPending={translationPending}
>
{title}
</ChallengeTitle>
<ChallengeDescription
description={description}
instructions={instructions}
/>
<Spacer size='m' />
<SolutionForm
challengeType={challengeType}
description={description}
// eslint-disable-next-line @typescript-eslint/unbound-method
onSubmit={this.handleSubmit}
updateSolutionForm={updateSolutionFormValues}
/>
<ProjectToolPanel
guideUrl={getGuideUrl({ forumTopicId, title })}
/>
<br />
<Spacer size='m' />
</Col>
<CompletionModal />
<HelpModal challengeTitle={title} challengeBlock={blockName} />
</Row>
</Container>
</LearnLayout>
</Hotkeys>
);
}
}
Project.displayName = 'Project';
return (
<Hotkeys
containerRef={container}
nextChallengePath={nextChallengePath}
prevChallengePath={prevChallengePath}
>
<LearnLayout>
<Helmet
title={`${blockNameTitle} | ${t('learn.learn')} | freeCodeCamp.org`}
/>
<Container>
<Row>
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
<Spacer size='m' />
<ChallengeTitle
isCompleted={isChallengeCompleted}
translationPending={translationPending}
>
{title}
</ChallengeTitle>
<ChallengeDescription
description={description}
instructions={instructions}
/>
<Spacer size='m' />
<SolutionForm
challengeType={challengeType}
description={description}
onSubmit={handleSubmit}
updateSolutionForm={updateSolutionFormValues}
/>
<ProjectToolPanel
guideUrl={getGuideUrl({ forumTopicId, title })}
/>
<br />
<Spacer size='m' />
</Col>
<CompletionModal />
<HelpModal challengeTitle={title} challengeBlock={blockName} />
</Row>
</Container>
</LearnLayout>
</Hotkeys>
);
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(withTranslation()(Project));
)(withTranslation()(ShowFrontEndProject));
export const query = graphql`
query ProjectChallenge($id: String!) {