1>***.obj : error LNK2001: 확인할 수 없는 외부 기호 _vsnprintf_s
1>***.obj : error LNK2001: 확인할 수 없는 외부 기호 sscanf_s

 

위와 같은 에러를 만났다면, 아래와 같이 처리 해보시기 바랍니다.

 

기존 낮은버전의 VisualStudio 에서 생성한 프로젝트를 높은 버전의 VisualStudio 에서 열어서 컴파일할때,

ex) vc2010 또는 vc2015 에서 생성한 프로젝트를 vc2022 에서 열어서 빌드할경우 위와 같은 에러 메세지를 출력

 

프로젝트 속성 페이지를 열어 링커 > 입력 > 추가종속성에 

legacy_stdio_definitions.lib 를 추가

 

 

 

 

1>"zwnmsd.vcxproj" 프로젝트를 빌드했습니다.
========== 모두 다시 빌드: 1 성공, 0 실패, 0 건너뛰기 ==========
========== 다시 빌드이(가) 오전 10:52에 완료되었으며, 17.992 초이(가) 걸림 ==========

 

정상적으로 컴파일이 되는 것을 확인.

1.  아래 링크에서 자신의 앱을 검색
    https://tools.applemediaservices.com/app-store/

 

Market with App Store

Easily create custom marketing assets to share your app on social media or web banners. Simply search for your app, choose a template, customize your design, and add preset messages in multiple languages. Learn more 

tools.applemediaservices.com

 

2. 앱을 클릭하여 상세 페이지로 이동

3. Link 주소를 복사하여 사용해도 되고  이미지를 직접 다운 로드 받아서 작업 해도 된다.

1.  아래 링크에서 자신의 앱을 검색
  https://play.google.com/store/games?device=windows

 

 

 

2. 주소창에  나와있는 앱 URL 을 복사
  https://play.google.com/store/apps/details?id=com.ccassak.wsf

 

 

3. 구글 플레이 뱃지 이미지 얻기
   아래의 URL 로 접속
   https://play.google.com/intl/en_us/badges/

 

위 화면에서 Play Store URL  인풋창에 자신의 앱 URL 을 넣으면, 왼쪽 HTML 링크가 생성됨

이미지 소스는 url 을 토해 가져다 쓰는 것이기 때문에 사이즈가 큼

본인은 뱃지를 다운 받아서 사이즈를 작게 조절하였음.

 

100% — FF
99% — FC
98% — FA
97% — F7
96% — F5
95% — F2
94% — F0
93% — ED
92% — EB
91% — E8
90% — E6
89% — E3
88% — E0
87% — DE
86% — DB
85% — D9
84% — D6
83% — D4
82% — D1
81% — CF
80% — CC
79% — C9
78% — C7
77% — C4
76% — C2
75% — BF
74% — BD
73% — BA
72% — B8
71% — B5
70% — B3
69% — B0
68% — AD
67% — AB
66% — A8
65% — A6
64% — A3
63% — A1
62% — 9E
61% — 9C
60% — 99
59% — 96
57% — 94
56% — 91
56% — 8F
55% — 8C
54% — 8A
53% — 87
52% — 85
51% — 82
50% — 80
49% — 7D
48% — 7A
47% — 78
46% — 75
45% — 73
44% — 70
43% — 6E
42% — 6B
41% — 69
40% — 66
39% — 63
38% — 61
37% — 5E
36% — 5C
35% — 59
34% — 57
33% — 54
32% — 52
31% — 4F
30% — 4D
28% — 4A
28% — 47
27% — 45
26% — 42
25% — 40
24% — 3D
23% — 3B
22% — 38
21% — 36
20% — 33
19% — 30
18% — 2E
17% — 2B
16% — 29
15% — 26
14% — 24
13% — 21
12% — 1F
11% — 1C
10% — 1A
9% — 17
8% — 14
7% — 12
6% — 0F
5% — 0D
4% — 0A
3% — 08
2% — 05
1% — 03
0% — 00

 

#1. 적당한 위치에 백업 폴더를 생성

#2. 스크립트 작성

 $ vi backup.sh

#!/bin/bash

now=`date +%Y%m%d`
dest="volab-backup-$now.tar.gz"
tar cvfz /var/backup/$dest /var/www/volab/

#3. 스크립트 실행

$ ./backup.sh

#4. 이걸 crontab 에 등록 하여 하루에 한번 백업을 실행하도록

# crontab -l   <- 작업 리스트 보기

# crontab -e  <- 작업 수정

# crontab -r   <- 모든 작업 삭제

 

$ crontab -e

5. 매일 새벽 01시에 실행

00 1 * * * /var/backup.sh

 

#5. 작업이 등록되어 있는지 확인

[root@vultr backup]# crontab -l
00 1 * * * /var/backup.sh

 

#6. 서비스 재실행

[root@vultr backup]# service crond restart
Redirecting to /bin/systemctl restart crond.service

 

 

개인정보처리방침

<WSF> 이 (가) 취급하는 모든 개인정보는 개인정보보호법 등 관련 법령상의 개인정보보호 규정을 준수하여 이용자의 개인정보 보호 및 권익을 보호하고 개인정보와 관련한 이용자의 고충을 원활하게 처리할 수 있도록 다음과 같은 처리방침을 두고 있습니다.

1 개인정보의 처리 목적

  • ① <WSF>은(는) 어떠한 목적으로라도 개인정보를 처리하고 있지 않습니다.

2 개인정보의 처리 및 보유 기간 작성

  • ① 해당 사항이 없습니다.

3 정보주체와 법정대리인의 권리·의무 및 그 행사방법

  • ① 해당 사항이 없습니다.

4 처리하는 개인정보 항목

  • ① 해당 사항이 없습니다.

5 개인정보의 파기

  • ① 해당 사항이 없습니다.

6 개인정보 자동 수집 장치의 설치·운영 및 그 거부에 관한 사항

  • ① 해당 사항이 없습니다.

7 개인정보 보호책임자

  • 이름: 성현진
  • 이메일: sunghj0816@gmail.com

8 개인정보의 안전성 확보 조치

  • 개인정보의 암호화
    • ① 해당 사항이 없습니다.

9 개인정보처리방침의 변경

  • ① 해당 사항이 없습니다.

리눅스에서 .svn 폴더를 삭제
$ find . -name '.svn' -exec rm -rf {} \;

 

.svn 을 다른 문자열로 변경하여 원하는 폴더/파일을 삭제할 수 있다.

 

 

이글은 단순히 제가 격은 이슈를 해결하는 과정을 적은 글입니다. 올바른 방법이 아닐 수도 있습니다.

 

 

d3 chart를 사용하려고 했다가, npm build가 안되는 상태 발생..

여러가지 찾다보니, 

"react": "^17.0.2",   // 17버전에서 해당 라이브러리가 지원이 안되는 것 같았음. 그래서 17을 16으로 바꾸고 빌드하니 됨.

 

로컬로 서버를 실행하니 restapi로 데이터를 못가져오고 여러가지 에러가 발생함

 

생각나는 것은 <></> 이게 react 17부터 지원되는거 같음.

또 찾아보니 axio 라이브러리에서 오류가 발생 하는 것 같음.

 

axio 사용한 소스의 차이점은 async / await  와 주소를 풀경로로 쓴것과 안쓴것 차이.

확실한건 http-proxy-middleware 패키지를 사용해서 경로를 생략했는데 이게 안먹히는 것 같음.

 

 

 

기존에 사용하던 소스 


function FuncLaboratory() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  useEffect(() => {
      const fetchData = async () => {
          try {
              setError(null);
              setUsers(null);
              setLoading(true);
              const response = await axios.get(
                  '/api/***/'
              );
              setData(response.data);
          } catch (e) {
              setError(e);
          }
          setLoading(false);
      };

      fetchData();
  }, []);

  if (loading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!data) return null;
 
  return (
      <div>
              <MyLabTable dataSource={data}/>
          </div>            
      </div>
  );
}

 

변경한 소스

function FuncLaboratory() {
  
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    setError(null);
    setData(null);
    setLoading(true);

    axios.get('http://localhost:8888/api/***/'
    ).then(res => {
      setData(res.data);
    }).catch(e => {
      console.log((error));
      setError(e);
    });
    setLoading(false);
  }, []);
  
  if (loading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!data) return null;

  return (
      <div>
              <MyLabTable dataSource={data}/>
      </div>
  );
}

첨엔 몰랐는데 크롬웹에서 개발자 도구를 열어보니 아래 같은 경고가 주르륵 뜨고 있습니다.

 

index.js:1 Warning: Each child in a list should have a unique "key" prop.

Check the render method of `SnmpVendor`. See https://reactjs.org/link/warning-keys for more information.
    at WithStyles (http://localhost:3000/static/js/vendors~main.chunk.js:15919:31)
    at SnmpVendor (http://localhost:3000/static/js/main.chunk.js:890:3)
    at ConnectFunction (http://localhost:3000/static/js/vendors~main.chunk.js:82625:75)
    at Route (http://localhost:3000/static/js/vendors~main.chunk.js:86050:29)
    at Switch (http://localhost:3000/static/js/vendors~main.chunk.js:86252:29)
    at Router (http://localhost:3000/static/js/vendors~main.chunk.js:85685:30)
    at BrowserRouter (http://localhost:3000/static/js/vendors~main.chunk.js:85305:35)
    at div
    at Provider (http://localhost:3000/static/js/vendors~main.chunk.js:82338:20)
    at App

 

키가 중요하지 않는 컴포넌트들이라 어떻게 처리해야할지 고민 하던중에

유니크한 난수값을 주면 어떨까 해서 찾아보니 uuid() 라는 것을 사용하면 된다고 합니다.

 

$ npm install uuid

 

사용할땐 uuid 를 임포트 해주고, 사용할 컴포넌트에 추가해주면 됩니다.

 

import { v4 as uuidv4 } from 'uuid';

 

const valCount = loading ? (<div>loading...</div>) : (

    vendorCnt.map(item => (

      <Typography key={uuidv4()} variant="body2"> 샘플 </Typography>

    ))

  )

 

 

 

 

 

 

 

앞서 주의사항!

 - 저도 공부하는 중이라 이해도가 낮아 설명에 있어서 부족한 부분이 있을 수 있습니다.

 - 하지만 도움이 되실 분도 있으리라 생각합니다.

 

목적: 검색어 자동 완성 만들어볼 것 (with antd)

 - App.js

  + src

    +--- App.js

 

 - 준비 : antd (ant design lib)

   ant design ui 라이브러리를 사용하여 좀더 미려하고 쉽게 구현을 해보자

 

프로젝트를 생성하고 vs code실행

> npx create-react-app test

> cd test

> npm i antd

> code .

 

해야할 일

- 기본적인 검색어 자동 완성에 대한 코드는 아래에서 참고.

 

 

[REACT] 검색어 자동완성 만들어보기

앞서 주의사항!  - 저도 공부하는 중이라 이해도가 낮아 설명에 있어서 부족한 부분이 있을 수 있습니다.  - 하지만 도움이 되실 분도 있으리라 생각합니다. 검색어 자동 완성 만들어볼 것  - App

ososoi.tistory.com

 

소스코드

antd 기본 샘플 예제

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { AutoComplete } from 'antd';
const { Option } = AutoComplete;

const Complete = () => {
const [result, setResult] = useState([]);

const handleSearch = (value) => {
let res = [];

if (!value || value.indexOf('@') >= 0) {
res = [];
} else {
res = ['gmail.com', '163.com', 'qq.com'].map((domain) => `${value}@${domain}`);
}

setResult(res);
};

return (
<AutoComplete
style={{
width: 200,
}}
onSearch={handleSearch}
placeholder="input here"
>
{result.map((email) => (
<Option key={email} value={email}>
{email}
</Option>
))}
</AutoComplete>
);
};

ReactDOM.render(<Complete />, document.getElementById('container'));

- 기본 샘플을 실행 시켜보고 내가 원하는 컨셉으로 수정~

  기본 샘플 예제는 input 박스에 텍스트 입력시 그텍스트를 가지고 약속된 email 주소를 자동 완성해주는 예제

 

 

수정

 - rest 서버에서 대상 데이터들을 받아왔다고 가정하고 가상 데이터들을 추가

 - 테이타풀에서 매치되는 것을 찾아서 출력

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { AutoComplete } from 'antd';
const { Option } = AutoComplete;

const datas = [
  {value:'삼성전자'},
  {value:'삼성바이오로직스'},
  {value:'LG전자'},
  {value:'LG화학'},
  {value:'DL'},
]

const App = () => {
  return (
    <Complete/>
  )
};

const Complete = () => {
  const [result, setResult] = useState([]);

  const handleSearch = (inputValue) => {
    let res = [];

    if (!inputValue) {
      res = [];
    } else {
      res = datas.filter(item => true === matchName(item.value, inputValue));
    }
    console.log('setResult', res);
    if (res.length > 0) {
      setResult(res);
    }
  };

  const matchName = (name, keyword) => {
    //console.log('matchName', name, keyword);
    if(name.toUpperCase().indexOf(keyword.toUpperCase()) !== -1)
    {
      console.log('matchName true');
      return true;
    }
    else {
      console.log('matchName false');
      return false;
    }
  };

  return (
    <AutoComplete
      style={{
        width: 200,
      }}
      onSearch={handleSearch}
      placeholder="input here"
      // filterOption={(inputValue, option) =>
      //   option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
      // }
    >
     {result.map((item) => (
          <Option key={item.value}> {item.value}</Option>
      ))}
    </AutoComplete>
  );
};


export default App;

 

실행

> npm run start

 

결과화면

 

 

 

앞서 주의사항!

 - 저도 공부하는 중이라 이해도가 낮아 설명에 있어서 부족한 부분이 있을 수 있습니다.

 - 하지만 도움이 되실 분도 있으리라 생각합니다.

 

SELECT 만들어볼 것

 - App.js

  + src

    +--- App.js

 

프로젝트를 생성하고 vs code실행

> npx create-react-app test

> cd test

> code .

 

소스코드

import logo from './logo.svg';
import './App.css';
import * as React from "react";


function App() {
  // 데이타를 준비
  const lookup =
    [
      { id: '1', query: '001', text: '조건검색1-1' },
      { id: '2', query: '001', text: '조건검색1-2' },
      { id: '3', query: '001', text: '조건검색2-1' },
      { id: '4', query: '002', text: '조건검색2-2' },
      { id: '5', query: '002', text: '조건검색2-3' }
    ];

  // state 사용
  const [selected, setSelected] = React.useState("");

  // 셀렉트 컴포넌트가 변경될때 불려짐
  const changeSelectOptionHandler = (event) => {
    setSelected(event.target.value);
  };

  // 선택된 아이템에 따라 값을 비교하고 데이타를 리턴
  var inquiries = lookup.filter(data => {
    if (selected === "001" && data.query.toLocaleLowerCase() === "001") {
      return data;
    } else if (selected === "002" && data.query.toLowerCase() === "002") {
      return data;
    }
  })

  return (
    <div
      style={{
        padding: "16px",
        margin: "16px",
      }}
    >
      <div>
        {/** onChange 될때 changeSelectOptionHandler 함수가 불려지도록 바인드
           */}
        <select onChange={changeSelectOptionHandler}>
          <option value="001">조건검색1</option>
          <option value="002">조건검색2</option>
        </select>
      </div>
      <div>
        {/** inquiries의 모든 텍스트를 출력
           */}
        {inquiries.map(inquiry => (
          <h3 >{inquiry.text}</h3>
        ))}
      </div>
    </div>
  );
}

export default App;

실행

> npm run start

 

결과화면



앞서 주의사항!

 - 저도 공부하는 중이라 이해도가 낮아 설명에 있어서 부족한 부분이 있을 수 있습니다.

 - 하지만 도움이 되실 분도 있으리라 생각합니다.

 

검색어 자동 완성 만들어볼 것

 - App.js, SearchBar.js (파일 생성)

  + src

    +--- App.js

    +--- SearchBar.js

 

프로젝트를 생성하고 vs code실행

> npx create-react-app test

> cd test

> code .

 

소스코드

// App.js
import './App.css';
import React, { useState } from "react";
import SearchBar from './SearchBar';

// App.js 에 기본적으로 추가되는 코드를 정리하고 심플하게 만듦
function App() {

//검색에 필요한 원천 데이타, 검색어, 결과값 
const data = [
    {"name":"키움증권""code":"000000"},
    {"name":"삼성전자""code":"000002"},
    {"name":"LG전자""code":"000003"},
    {"name":"스튜디오드래곤""code":"000004"},
    {"name":"영호화학""code":"000005"},
    {"name":"씨젠""code":"000006"},
    {"name":"LG화학""code":"000007"}, 
    {"name":"DL""code":"000008"},
    {"name":"오뚜기""code":"000009"},
  ];  
  const [keyword, setKeyword] = useState();
  const [results, setResult] = useState([]);
  
  // 필드를 업데이트 
  const updateField = (field, value, update = true=> {
    if (update) onSearch(value);
    if (field === 'keyword') {
      setKeyword(value);
    }
    if (field === 'results') {
      setResult(value);
    }
  }
  
  // 입력된 텍스트로 data 배열에서 찾아 매칭되는 결과들을 저장 
  const onSearch = text => {
    var results = data.filter(item => true === matchName(item.name, text));
    setResult({ results });
  };

 // 검색해야할 문자열을 키워드와 비교하여 매칭이 되는지 체크 
   const matchName = (name, keyword) => {
    var keyLen = keyword.length;
    name = name.toLowerCase().substring(0, keyLen);
    if (keyword === ""return false;
    return name === keyword.toString().toLowerCase();
  };

  
  return (
    <div className="App">
          Search Auto Complete
          <SearchBar keyword={keyword} results={results} updateField={updateField}></SearchBar>
    </div>
  );
}

export default App;
 

 

// SearchBar.js

import React from "react";

// 키워드, 결과값들, 업데이트필드를 전달받는다
const SearchBar = ({ keyword, results, updateField }) => {

  // 
    const updateText = text => {
        //console.log('update text', text);
        updateField("keyword", text, false);
        updateField("results", []);
    };
    
    var renderResults;
    const arr = results['results'];
    if(arr) {
    // arr 에 검색어에 대한 결과가 담기면, SearchView 호출 
    renderResults = arr.map((item => {
            return (
                <SearchView
                    updateText={updateText}
                    name={item.name}
                    code={item.code}
                    key={item.code}
                />
            );
        }));
    }
    // onChange를 사용하여 글자를 입력할때마다 updateField호출하고 renderResults를 그린다.
    return (
        <div className="auto">
            <input
                className="search-bar"
                placeholder="Search"
                value={keyword || ''}
                onChange={=> updateField("keyword", e.target.value)}
            />
            <div className="search-results">{renderResults}</div>
        </div>
    );
};

// 검색된 아이템 "naem" "code" 출력
// 결과값을 클릭하면 updateText를 호출하여 input에 name을 표시
const SearchView = ({ name, code, index, updateText }) => {
    //console.log('search view:', name);

    return (
      <div
        onClick={() => updateText(name)}
        className={`search-preview ${index === 0 ? "start" : ""}`}
      >
        <div className="first">
          <p className="name">{name}</p>
          <p className="code">{code}</p>
        </div>
      </div>
    );
  };

export default SearchBar;

 

실행

> npm run start

 

 

결과화면

준비물 : 로고로 쓰일 이미지 원본 (사이즈는 1080  x 1920 정도가 적당하다고 합니다)

           저는 파일명:logo.jpg, 512x512 사이즈로 준비해봤습니다.

 

 

프로젝트 창에서 새로운 리소스 파일을 생성

 - intro_layout.xml 이라고 네이밍

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/my_image"
/>
</LinearLayout>

intro_layout.xml 내용을 위와 같이 만들어 줍니다. @drawable/[로고로 쓰일 이미지 파일명]

저는 logo 이기 때문에 @drawable/logo

 

프로젝트 창에 추가되는 파일들

다음으로 IntroActivity 클래스를 만들어줍니다.

내용은 MainActivity 있는 껍데기 것을 고대로 가져다가 만들어줍니다. 

R.layout.activity_main 을 R.layout.intro_layout 으로 변경했습니다.

package com.kkassak.vostock

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class IntroActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.intro_layout)
    }
}

 

다음으로 인트로가 시작되면 1초 대기후 메인으로 넘어가는 코드를 추가하겠습니다.

package com.kkassak.vostock

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler


class IntroActivity: AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.intro_layout)

    var handler = Handler()
    handler.postDelayed({var intent = Intent(this, MainActivity::class.java)
    startActivity(intent)
    }, 1000)
  }

  override fun onPause() {
    super.onPause()
    finish()
  }
}

여기서 인트로 액티비티를 먼저 시작해야 하기 때문에 매니패스트 파일(AndroManifest.xml)을 변경합니다.

붉은색 글씨를 봐주세요. 새로운 액티비티를 추가하고 main <-> intro 를 바꿔줍니다

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kkassak.vostock">

<application
android:usesCleartextTraffic="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar">
<activity android:name=".IntroActivity"
android:theme="@style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity"></activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

 

앱을 실행시켜서 인트로 화면이 잘 나오는지 확인 합니다.

사이트를 만들고 한동안 고민이었던게 네비게이션바의 메뉴를 누르고 상태가 활성화 된 상태에서 F5를 누르면 다시 초기화가 되는 현상을 어떻게 하면 해결할 수 있나 하는 거였는데, 

 

state 를 사용하면 된다는데 일단 여러가지로 알아본 결과 젤 간단한 방법을 찾아서 적용했고 결과는 Ok

 

웹쪽 개발은 전무하기 때문에... 일단 닥치는 대로 만들고.. 만들고 하다보면서 기반 기술을 조금씩 익혀가는..

어쨓든 실전이라 생각하고 결과물을 만들어 내고 부딪히고 깨지면서 하나씩 알아가는 즐거움도 있는 것 같다.

 

sessionStorage 를 사용하는 것인데, localStorage 라는 것도 있다. 이 둘의 차이는 구글링을 해서 알아보면 되고.

sessionStorage 는 키, 벨류로 사용한다.

 

sessionStorage.setItem('key', value);

sessionStorage.getItem('key');

 

아래는 실제로 사용했던 코드 일부로 설명

 

메뉴의 섹션 정보를 만들고

const sections = [

    { key:'1', title: 'Home', url: '/' },

    { key:'2', title: '재무분석', url: '/jaemuratio' },

]

 

메뉴버튼을 클릭하면 'menu'라는 키에 값을 저장해둠

    menuClick(title) {

        sessionStorage.setItem('menu', title);

    };

 

메뉴 구성은 아래와 같다. 메뉴클릭 함수에 해당 메뉴의 키를 전달한다

<Menu.Item key="1">

     <Link to={sections[0].url} onClick={() => this.menuClick(sections[0].key)} />

     <span>{sections[0].title}</span>

 </Menu.Item>

 

컴포넌트의 컨스트럭터에 최초에는 메뉴가 선택이 안되어 있기 때문에 강제로 1번(home) 을 보여주고 값이 설정되어 있으면 마지막에 저장되어 있는 값을 꺼내온다.

constructor(props) {

        super(props);

        let item = sessionStorage.getItem('menu');

        if(item === null)

        {

          sessionStorage.setItem('menu''1');

        }

    };

class App extends Component {

  componentDidMount() {
    document.title = "VoCoin";
  }

}

 

또는

public 폴더 아래에 index.html 직접 수정

 

<title>VoCoin</title>

+ Recent posts