mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
refactor(client): convert backend to functional component (#57401)
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
|
||||
import { graphql } from 'gatsby';
|
||||
import React, { Component } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import type { TFunction } from 'i18next';
|
||||
@@ -95,59 +91,18 @@ interface BackEndProps {
|
||||
updateSolutionFormValues: () => void;
|
||||
}
|
||||
|
||||
// Component
|
||||
class BackEnd extends Component<BackEndProps> {
|
||||
static displayName: string;
|
||||
private container: React.RefObject<HTMLElement> = React.createRef();
|
||||
const ShowBackEnd = (props: BackEndProps) => {
|
||||
const container = useRef<HTMLElement>(null);
|
||||
|
||||
constructor(props: BackEndProps) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.updateDimensions = this.updateDimensions.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
}
|
||||
const handleSubmit = ({
|
||||
showCompletionModal
|
||||
}: {
|
||||
showCompletionModal: boolean;
|
||||
}) => {
|
||||
props.executeChallenge({ showCompletionModal });
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.initializeComponent();
|
||||
window.addEventListener('resize', () => this.updateDimensions());
|
||||
this.container.current?.focus();
|
||||
}
|
||||
|
||||
updateDimensions() {
|
||||
this.setState({ width: window.innerWidth, height: window.innerHeight });
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', () => this.updateDimensions());
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: BackEndProps) {
|
||||
const {
|
||||
data: {
|
||||
challengeNode: {
|
||||
challenge: {
|
||||
title: prevTitle,
|
||||
fields: { tests: prevTests }
|
||||
}
|
||||
}
|
||||
}
|
||||
} = prevProps;
|
||||
const {
|
||||
data: {
|
||||
challengeNode: {
|
||||
challenge: {
|
||||
title: currentTitle,
|
||||
fields: { tests: currTests }
|
||||
}
|
||||
}
|
||||
}
|
||||
} = this.props;
|
||||
if (prevTitle !== currentTitle || prevTests !== currTests) {
|
||||
this.initializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
initializeComponent() {
|
||||
useEffect(() => {
|
||||
const {
|
||||
challengeMounted,
|
||||
initConsole,
|
||||
@@ -164,7 +119,7 @@ class BackEnd extends Component<BackEndProps> {
|
||||
}
|
||||
},
|
||||
pageContext: { challengeMeta }
|
||||
} = this.props;
|
||||
} = props;
|
||||
initConsole();
|
||||
initTests(tests);
|
||||
updateChallengeMeta({
|
||||
@@ -174,112 +129,99 @@ class BackEnd extends Component<BackEndProps> {
|
||||
helpCategory
|
||||
});
|
||||
challengeMounted(challengeMeta.id);
|
||||
}
|
||||
container.current?.focus();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
handleSubmit({
|
||||
showCompletionModal
|
||||
}: {
|
||||
showCompletionModal: boolean;
|
||||
}): void {
|
||||
this.props.executeChallenge({
|
||||
showCompletionModal
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
data: {
|
||||
challengeNode: {
|
||||
challenge: {
|
||||
fields: { blockName },
|
||||
challengeType,
|
||||
forumTopicId,
|
||||
title,
|
||||
description,
|
||||
instructions,
|
||||
translationPending,
|
||||
superBlock,
|
||||
block
|
||||
}
|
||||
const {
|
||||
data: {
|
||||
challengeNode: {
|
||||
challenge: {
|
||||
fields: { blockName },
|
||||
challengeType,
|
||||
forumTopicId,
|
||||
title,
|
||||
description,
|
||||
instructions,
|
||||
translationPending,
|
||||
superBlock,
|
||||
block
|
||||
}
|
||||
},
|
||||
isChallengeCompleted,
|
||||
output,
|
||||
pageContext: {
|
||||
challengeMeta: { nextChallengePath, prevChallengePath }
|
||||
},
|
||||
t,
|
||||
tests,
|
||||
updateSolutionFormValues
|
||||
} = this.props;
|
||||
}
|
||||
},
|
||||
isChallengeCompleted,
|
||||
output,
|
||||
pageContext: {
|
||||
challengeMeta: { nextChallengePath, prevChallengePath }
|
||||
},
|
||||
t,
|
||||
tests,
|
||||
updateSolutionFormValues
|
||||
} = props;
|
||||
|
||||
const blockNameTitle = `${t(
|
||||
`intro:${superBlock}.blocks.${block}.title`
|
||||
)} - ${title}`;
|
||||
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}
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
onSubmit={this.handleSubmit}
|
||||
updateSolutionForm={updateSolutionFormValues}
|
||||
/>
|
||||
<ProjectToolPanel
|
||||
guideUrl={getGuideUrl({ forumTopicId, title })}
|
||||
/>
|
||||
<br />
|
||||
<Output
|
||||
defaultOutput={`/**
|
||||
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}
|
||||
onSubmit={handleSubmit}
|
||||
updateSolutionForm={updateSolutionFormValues}
|
||||
/>
|
||||
<ProjectToolPanel
|
||||
guideUrl={getGuideUrl({ forumTopicId, title })}
|
||||
/>
|
||||
<br />
|
||||
<Output
|
||||
defaultOutput={`/**
|
||||
*
|
||||
* ${t('learn.test-output')}
|
||||
*
|
||||
*
|
||||
*/`}
|
||||
output={output}
|
||||
/>
|
||||
<TestSuite tests={tests} />
|
||||
<Spacer size='m' />
|
||||
</Col>
|
||||
<CompletionModal />
|
||||
<HelpModal challengeTitle={title} challengeBlock={blockName} />
|
||||
</Row>
|
||||
</Container>
|
||||
</LearnLayout>
|
||||
</Hotkeys>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
BackEnd.displayName = 'BackEnd';
|
||||
output={output}
|
||||
/>
|
||||
<TestSuite tests={tests} />
|
||||
<Spacer size='m' />
|
||||
</Col>
|
||||
<CompletionModal />
|
||||
<HelpModal challengeTitle={title} challengeBlock={blockName} />
|
||||
</Row>
|
||||
</Container>
|
||||
</LearnLayout>
|
||||
</Hotkeys>
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToActions
|
||||
)(withTranslation()(BackEnd));
|
||||
)(withTranslation()(ShowBackEnd));
|
||||
|
||||
export const query = graphql`
|
||||
query BackendChallenge($id: String!) {
|
||||
|
||||
Reference in New Issue
Block a user