mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-02-22 05:01:23 -05:00
chore: convert frontend to functional component (#57395)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -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!) {
|
||||
|
||||
Reference in New Issue
Block a user