이 블로그에서는 다음을 수행할 것입니다. Typescript에 대해 알아보세요 그리고 나는 당신에게 방법을 보여줄 것입니다 귀하의 속성을 사용하세요 Mendix 위젯의 모델, 어떻게 브라우저 API 활용 그리고 우리는 심지어 이것에 대해서도 다룰 것입니다 React의 조건부 렌더링.
이것은 여러 부분으로 구성된 시리즈의 두 번째 블로그입니다. 블로그 1은 여기에서 찾을 수 있습니다. 위젯을 빌드하세요 Mendix React로 - 1부 - 색상 카운터
Pluggable Widgets를 사용하는 경우
새로운 Pluggable 위젯을 생성할지 여부를 결정할 때 사용하는 몇 가지 시금석이 있습니다.
- UI 구성 요소가 필요합니까? — Javascript를 사용해야 하지만 UI 구성 요소가 없는 경우 JS 액션 귀하의 사용 사례에 더 적합할 수 있습니다
- 에서 사용 가능한가요? Mendix 온라인마켓?
- 브라우저 API나 NPM 패키지를 사용하나요?
우리가 무엇을 만들고 있는가
이번에는 우리가 건설할 것입니다 고정된 간격으로 페이지를 새로 고치는 타이머. "왜 그냥 JavaScript로 하지 않을까요?"라고 묻는 게 들립니다. 그 이유는 시각적인 구성 요소도 있기 때문입니다. 다음 새로 고침까지 얼마나 걸리는지 알려줍니다..

이는 대시보드가 작업 현장에 표시되고 30초마다 업데이트되어야 하는 실제 사용 사례를 기반으로 했습니다.

시작 가이드
이 위젯에서는 다음을 사용합니다. 타이프 스크립트, Javascript를 둘러싼 강력한 형식 래퍼는 처음에는 코드를 작성하기가 약간 더 어렵게 만들지만 내장된 린팅 및 광범위한 문서 Pluggable Widgets를 만들 때 매우 유용합니다. Typescript의 이러한 요소는 또한 대규모 팀에서 협업하기가 더 쉽습니다. 및 복잡한 API와 통합.

우리는 위젯을 스캐폴딩하는 것으로 시작합니다. 블로그 1 하지만 이번에는 프로그래밍 언어로 Typescript를 선택했습니다.
React에서 함수형 컴포넌트와 클래스 컴포넌트에 대한 간단한 참고 사항. 이 블로그 전체에서 우리는 기능적 구성 요소를 사용할 것입니다, 그러나 당신은 또한 할 수 있습니다 클래스 컴포넌트를 사용하여 작성된 React를 접하다. 이 때문입니다, 까지 후크의 릴리스 React 16.8에서, 클래스 구성 요소는 상태를 관리하는 유일한 방법이었습니다., 그리고 기능적 구성 요소는 주로 프런트엔드의 프레젠테이션 계층이었습니다. 이제 React 커뮤니티는 기능적 구성요소를 사용하는 방향으로 이동 그들은 그대로 구문적으로 더 간단하다 그리고 더 경량의.
개발 시간
Pluggable Widget 폴더 구조에 대한 설명과 개발 환경을 설정하는 방법은 내 것을 참조하세요. 이전 블로그.
먼저 한 가지
개발 프로세스를 가속화하기 위해 편집기 미리보기 파일을 제거합니다. 이 파일은 Studio Pro 또는 Studio의 디자인 모드에서 위젯의 미리보기를 생성하며, 이 가이드에서는 걱정하지 않습니다. 업데이트할 것이 하나 더 있을 뿐입니다. 그러니 파일을 제거해 보겠습니다. 타이머.에디터미리보기.tsx.
브리핑
위젯을 통해 달성하려는 목표는 3가지 주요 섹션으로 나눌 수 있습니다.
- 1 단계 : 타이머를 정의된 초기값으로 설정합니다. Mendix
- 2 단계 : 타이머를 1초 간격으로 감소시킵니다.
- 3 단계 : 동작 실행
1단계: 타이머를 정의된 초기값으로 설정합니다. Mendix
우리 사이의 인터페이스를 만드는 것으로 시작해 보겠습니다. Mendix 모델과 위젯. 간단한 Integer를 사용할 수 있지만 속성을 사용하면 런타임에 타이머 값을 동적으로 변경할 수 있는 유연성이 더 커집니다.
Timer.xml을 업데이트하여 다음을 포함합니다.
<property key="timeAtt" type="attribute" required="true
<caption>Time attribute</caption>
<description>The number of seconds on refresh</description>
<attributeTypes>
<attributeType name="Integer"/>
</attributeTypes>
</property>
그러는 동안 자식 구성 요소를 TimeText로, 인터페이스를 TimeTextProps로 이름을 바꿔야 합니다. 파일을 저장하고 명령을 실행할 때:npm run build, 오류가 표시됩니다. 이것은 좋습니다!

sampleText 속성이 timeAtt로 대체되었음을 보여줍니다. 기본 sampleText 대신 timeAtt로 Timer 파일을 업데이트해 보겠습니다.
Timer.tsx 파일에서 timeAtt를 강조 표시하면 이것이 유형임을 알 수 있습니다. EditableValue<Big>.
편집 가능한 값 이다 일반 유형 그 Mendix 모든 속성을 나타내는 데 사용되며 이를 통해 속성을 읽고 쓸 수 있습니다. Mendix 모델입니다.
'<>' 부분은 속성 유형에 의해 결정됩니다. 정수 또는 소수 속성의 경우 Big.js 라이브러리를 사용합니다. 이는 애플리케이션에서 사용되는 숫자가 기본 JavaScript 숫자 제한에 의해 제한되지 않도록 하기 위한 것입니다.
사용 상태
지금까지 우리는 다음과 같은 링크를 생성했습니다. Mendix 그리고 위젯은 컨테이너 구성 요소의 props를 통해 전달됩니다. 이제 페이지에 표시하기 위해 TimeText 구성 요소에 쉽게 읽을 수 있는 값을 전달해야 합니다. 이를 위해 우리는 다음을 처리합니다. EditableValue<Big> 그리고 간단한 정수를 저장합니다. 상태 컨테이너 구성 요소의 경우.
우리는 사용 상태 여기보다는 소품 시간이 지남에 따라 타이머 값을 변경하게 되기 때문입니다. 소품은 절대로 직접 변경해서는 안 됩니다.:
가져오기부터 시작해 보자 사용 상태 'React'에서 초기화 상태 라는 시간 다음과 같이
const [time, setTime] = useState<number>();
이것은 우리에게 상태 변수를 제공합니다 (시간) 그리고 해당 상태를 변경하기 위한 setState 함수(props와 마찬가지로 상태는 결코 직접 변경되어서는 안 되며, 대신 이 함수를 통해 변경할 수 있음)가 있습니다.
useEffect 사용하기
다음으로 우리는 우리의 속성 값을 우리의 상태에 전달합니다. 이를 수행하는 가장 쉬운 방법은 useState에 값을 전달하는 것입니다.
const [time, setTime] = useState<number>(timeAtt.value.toNumber());
하지만 우리의 값이 비어 있을 수 있기 때문에, 우리는 그렇게 하지 않을 것입니다. 대신, 우리는 React의 또 다른 중심 개념인 'useEffect'를 사용할 것입니다.
그럼 useEffect는 무엇일까요? 기본적으로 모든 렌더링 후에 함수를 실행합니다. 이를 사용하여 다음과 같이 시간을 설정할 수 있습니다.
export function Timer({timeAtt}: TimerContainerProps):ReactElement {
const [time, setTime] = useState<number>();
useEffect(() => {
if (timeAtt.value) {
setTime(timeAtt.value.toNumber());
}
}, []);
return <TimeText sampleText={sampleText ? sampleText:"World"}/>;
}
그런 다음 새 시간 상태를 허용하도록 props를 업데이트하여 자식 구성 요소인 TimeText로 이를 전달할 수 있습니다.
return <TimeText value={time}/>;
이제 Timer 컴포넌트가 업데이트되었습니다!
이제 TimeText 구성 요소에 몇 가지 사소한 변경을 해야 합니다. 새로운 소품을 받아들이다. Typescript를 사용하고 있기 때문에 인터페이스 우리 구성 요소에 대해. 이것은 이 구성 요소를 사용하는 모든 코드가 어떻게 상호 작용할 수 있는지 정의합니다. 따라서 디스플레이 구성 요소를 다음과 같이 업데이트해 보겠습니다.
export interface TimeTextProps {
value: number | undefined;
}
export function TimeText({ value }: TimeTextProps): ReactElement {
return <div>{value} seconds</div>;
}
여기에서는 인터페이스가 불필요해 보일 수 있으며 이와 같은 작은 위젯의 경우에는 그럴 가능성이 있지만 프로젝트가 커질수록 매우 유용합니다..
테스트하려면 열 수 있습니다 Mendix Studio Pro를 사용하고 F4를 눌러 업데이트를 위젯과 동기화합니다. 그런 다음 숫자 속성을 타이머 위젯에 전달할 수 있도록 페이지를 설정해야 합니다.

We 실행을 클릭하세요 그리고…. 저희 페이지에는 '초'라고만 적혀있습니다.

걱정 마세요. 이것은 어떻게 인해 예상됩니다 Mendix 속성을 로드합니다. 그만큼 속성 값은 비동기적으로 로드됩니다., 이것이 바로 이것을 만드는 것입니다 Mendix 프런트엔드는 매우 빠르지만 위젯을 작동시키려면 몇 줄의 추가 코드가 필요합니다.
useEffect를 사용하지만 올바르게
useEffect의 두 번째 매개변수를 비워두었습니다. 이는 useEffect 함수가 구성 요소가 처음 마운트될 때 한 번 실행됨을 의미합니다., 어느 시점에서 우리의 속성 값이 준비되지 않았습니다.
이것을 확인하려면 다음을 입력하세요. console.log(`Render ${timeAtt.value}`) if 문 위에 있는 브라우저 콘솔을 확인하세요(브라우저에서 'Ctrl + Shift + i').
그래서 우리는 timeAtt가 업데이트될 때마다 useEffect 함수가 실행되기를 원합니다. 이를 위해 useEffect의 두 번째 매개변수에 timeAtt를 추가하기만 하면 됩니다.
export function Timer({timeAtt}: TimerContainerProps):ReactElement {
const [time, setTime] = useState<number>();
useEffect(() => {
if (timeAtt.value) {
setTime(timeAtt.value.toNumber());
}
}, [timeAtt]);
return <TimeText value={time}/>;
}
응용 프로그램을 다시 실행하면 Mendix 타이머 값이 표시되고, 콘솔 로그를 확인하면 위젯이 두 번 렌더링된 것을 볼 수 있습니다. 한 번은 값이 정의되지 않았을 때이고, 한 번은 숫자일 때입니다.


성공! 1부가 끝났어요!
2단계: 1초 간격으로 타이머를 줄입니다.
멋지네요. 화면에 숫자가 표시되어 있지만 그게 별로 쓸모가 없어요. 우리는 타이머가 카운트다운되기를 원합니다. 그렇게 하기 위해 우리는 다음을 할 것입니다. 브라우저 Javascript API를 사용하세요. 구체적으로 window.setTimeout(), 그 고정된 시간 후에 함수를 실행합니다.
이것을 오랜 친구 useEffect와 결합하면 카운트다운을 만들 수 있습니다. useEffect 함수를 시간 상태에 따라 종속시키고 1초 동안 기다려서 변경하면 시간 1초씩 상태를 변경하면 기본적으로 루프가 생성됩니다.
export function Timer({timeAtt}: TimerContainerProps):ReactElement {
const [time, setTime] = useState<number>();
useEffect(() => {
if (timeAtt.value) {
setTime(timeAtt.value.toNumber());
}
}, [timeAtt]);
>seEffect(() => {
if (time !== undefined) {
window.setTimeout(() => setTime(time - 1), 1000);
}
}, [time]);
return <TimeText value={time}/>;
}
하지만 이 계산은 끝없이 계속될 것이므로 이를 멈추려면 하나의 조건을 더 추가해야 합니다.
useEffect(() => {
if (time !== undefined) {
if (time > 0) {
window.setTimeout(() => setTime(time - 1), 1000);
}
}
}, [time]);
위젯을 다시 로드하면 카운트다운이 표시되는 것을 볼 수 있습니다.

사용 중인 경우 알림 npm run start 위젯의 변경 사항을 살펴보세요 캐시를 지우고 새로 고침해야 합니다. (크롬에서 브라우저 도구를 열고 새로 고침 버튼을 마우스 오른쪽 버튼으로 클릭하세요)
3단계: 작업 실행
이제 카운트다운이 0에 도달하면 어떤 일이 일어나야 합니다!
운 좋게 Mendix 모델과 통합하고 작업을 실행하기 위한 매우 사용하기 쉬운 API를 제공합니다. 먼저 Timer.xml을 업데이트하여 다음을 포함합니다.
<property key="action" type="action" required="true">
<caption>Action</caption>
<description>Action to trigger when the time elapses</description>
</property>
그런 다음 Timer.tsx에서 동작을 실행하는 함수를 추가하고, useEffect 함수를 업데이트하여 0에서 동작을 실행할 수 있습니다.
최종 Timer.tsx는 다음과 같아야 합니다.
export function Timer({ timeAtt, action }: TimerContainerProps): ReactElement {
const [time, setTime] = useState<number>();
useEffect(() => {
if (time !== undefined) {
if (time > 0) {
window.setTimeout(() => setTime(time - 1), 1000);
} else {
execAction();
}
}
}, [time]);
useEffect(() => {
if (timeAtt.value) {
setTime(timeAtt.value.toNumber());
}
}, [timeAtt]);
const execAction = () => {
if (action && action.canExecute) {
action.execute();
}
};
return <TimeText value={time} />;
}
우리는 이 새로운 코드를 테스트할 수 있습니다 Mendix F4를 누르고 실행할 작업을 선택하여 앱을 실행합니다.

페이지를 새로 고치는 마이크로플로우를 호출하도록 선택하면 반복 타이머를 얻게 됩니다.
마지막으로 하나 더
컴포넌트가 처음 로드될 때 TimeText 컴포넌트에 전달된 시간 값이 정의되지 않은 짧은 기간이 있었습니다. 이는 위젯이 '초'를 렌더링하는 것으로 이어지기 때문에 큰 문제는 아니지만 값이 로드되고 있다는 표시를 하는 것이 가장 좋습니다.
그렇게 하기 위해 React에서 조건부 렌더링을 위한 일반적인 패턴을 사용할 것입니다.
if 문을 사용하면 값이 아직 정의되지 않았는지 확인하고 다음과 같이 로딩을 표시할 수 있습니다.
export function TimeText({ value }: TimeTextProps): ReactElement {
if (value === undefined) {
return <div>Loading</div>;
} else {
return <div>{value}</div>;
}
}
하지만 너무 장황하네요. 우리는 사용할 수 있습니다 ES6의 삼항 연산자 이것을 줄이면 다음과 같습니다.
export function TimeText({ value }: TimeTextProps): ReactElement {
return value ? <div>{value} seconds</div> : <div>Loading</div>;}
그리고 보세요!

제품 개요
축하합니다. 플러그인 위젯을 만들었습니다!
이 빌드에서는 Pluggable Widget API를 다루었으며 데이터를 가져오는 방법을 다루었습니다. Mendix 모델과 변경; Typescript를 사용하여 통합 방법을 더 잘 이해하도록 다루었습니다. Mendix 앱에서 React의 주요 개념을 다시 살펴보고 작업을 실행하는 방법을 배웠습니다. Mendix 위젯의 모델.
이 위젯의 최종 상태는 여기에서 확인할 수 있습니다. GitHub – joe-robertson-mx/timer
다음으로 우리는 다음을 사용하여 칸반 보드를 구축할 것입니다. Mendix 그리고 Pluggable Widgets를 통해 위젯을 결합하여 매끄러운 최종 사용자 경험을 만드는 방법과 변경 사항을 지속하는 방법에 대해 자세히 알아보세요. Mendix 데이터 베이스.