[React] Apexcharts Real-time Line chart

이경은·2023년 3월 14일
0

들어가기

AWS AppSync GraphQL의 Subscription을 사용해서 데이터가 실시간으로 들어오면 기존 배열에 새로운 값을 추가해서 실시간 차트를 구현했다.

How to use

Apexcharts line chart 변수 형태

  • series
    • y 축의 값을 가지고 있는 부분. 객체 배열.
    • [ { name: “humidity”, data: [ 10, 20, 30 ] }, { name: “humidity”, data: [ 10, 20, 30 ] } ]
  • categories
    • x 축의 값을 가지고 있는 부분. 시간 배열
    • [ 1678230384, 1678230384, 1678230384 ]

코드

  • useEffect를 통해서 event data를 subscription 한다.
  • 이벤트가 발생하면 next 안에 있는 로직이 실행되며, newValue라는 변수를 업데이트 시킨다.
  • 이벤트 데이터 중에서 modeledData가 값이 없는 경우가 아닐 때만 업데이트 시킨다.
  • newValue가 업데이트 되면, useEffect 훅을 통해서 다른 로직이 실행되도록 했다.
const [series, setSeries] = useState([]);
const [categories, setCategories] = useState([]);

const [newValue, setNewValue] = useState({});

useEffect(() => {
  const subscription = API.graphql(
    graphqlOperation(subscriptions.onCreateDeviceEvent, {
      deviceId: deviceId,
    })
  ).subscribe({
    next: (data) => {
      // console.log('new data', data.value.data.onCreateDeviceEvent);
      if (data.value.data.onCreateDeviceEvent.modeledData !== '{}') {
        setNewValue(data.value.data.onCreateDeviceEvent);
      }
    },
  });

  return () => {
    subscription.unsubscribe();
  };

}, []);
  • 아래 코드는 newValue가 변경되면 동작하는 useEffect()함수
  • useDidMountEffect는 첫 렌더링 시에 동작하지 않고, 배열 안의 변수가 변경될 때만 실행되도록 하는 useEffect의 custom hook이다.
useDidMountEffect(() => {
	// newValue의 modeledData를 string에서 json 형태로 parsing
  const newData = JSON.parse(newValue.modeledData);

	// 기존 카테고리에 newValue의 createdTime을 milisecond 단위로 변환해서 추가
	// 새로운 카테고리 배열 생성
  const newCategory = [...categories];
  newCategory.push(newValue.createdTime * 1000);

	// json 형태의 newData에서 key, value를 분리한다
  const keyArr = Object.keys(newData);
  const valueArr = Object.values(newData);

  let newSeries = [];

	// series의 length 가 0이면 기존에 값이 없다는 뜻.
	// series 형태를 만들어서 넣어줘야 함.
  if (series.length === 0) {
    newSeries = keyArr.map((item, idx) => {
      const tempdata = { name: item, data: [valueArr[idx]] };
      return tempdata;
    });
  } else { // 기존 series 값이 있음
    const seriesArr = keyArr.map((item, idx) => {
      let tempSeries = {};
			// series에서 name이 key 값과 일치하는 항목이 있는지 확인
			// 없으면 undefined 반환
      tempSeries = series.find((e) => e.name === item);

			// name이 key값과 일치하면
      if (tempSeries !== undefined) {
				// data 배열에 value를 추가함
        tempSeries.data.push(valueArr[idx]);
      }
      return tempSeries;
    });

		// 위에서 tempSeries가 undefined로 나온 것들을 filtering
    newSeries = seriesArr.filter((e) => e !== undefined);
  }
  // console.log('new graph value', newSeries, newCategory);

  setSeries(newSeries);
  setCategories(newCategory);
}, [newValue]);
profile
Web Developer

0개의 댓글