フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

駅JPのデータを利用して駅検索実装する(React/Express/Mysql)

はじめに

  • 駅JPのデータを利用して駅検索機能を作成する
  • バックエンド側でMySQLに登録されている駅JPのデータをjsonで返す
  • フロント側でバックエンド側のURLへアクセスしてjson形式でデータを取得してreact-selectで実装する

過去の記事をベースに実装

px-wing.hatenablog.com

px-wing.hatenablog.com

px-wing.hatenablog.com

px-wing.hatenablog.com

バックエンド 実装

router.get('/stations', async (req, res, next) =>{
  db.stations.findAll({
    attributes: ['station_cd', 'station_name','lon','lat'],
    where: Object.keys(req.query).length > 0 ?  req.query : {line_cd: 0},
  }).then((stations)=>{
    res.json(stations)
  });
})

router.get('/lines', async (req, res, next) => {
  db.companies.findAll({
    where: Object.keys(req.query).length > 0 ?  req.query : {company_cd: 0},
    include: [{
        model: db.lines,
        attributes: ['line_cd', 'line_name'],
        required: true
    }]
  }).then((lines)=>{
    res.json(lines)
  });
})

router.get('/companies', async (req, res, next) =>{
  db.companies.findAll({
    attributes: ['company_cd', 'company_name'],
  }).then((companies)=>{
    res.json(companies)
  });
})

フロント 実装

鉄道会社プルダウン

import React,{useState, useEffect} from 'react'
import Select from 'react-select'
import axios from 'axios'
import Lines from './Lines'

const Companies = () =>{
  const [companies, setCompanies] = useState([]);
  const [companyCd, setCompanyCd] = useState(0);
  const [companyName, setCompanyName] = useState('鉄道会社を選択して下さい');

  const getCmmpanies = async (barcode) => {
    const result = await axios.get(`<Your Web Site URL>/backend/api/companies`)
      .then(res => {
        const companies = res.data.map(companie => {
          return { value: companie.company_cd, label: companie.company_name }
        });
        setCompanies(companies)
    })
  }

  useEffect(() => {
    getCmmpanies();
  },[]);

  const changeCompany = (e) =>{
    setCompanyCd(e.value)
    setCompanyName(e.label)
  }

  return (
    <>
      <h4>駅検索</h4>
      <Select options={companies} onChange={changeCompany} value={{ value: companyCd, label: companyName }}/>
      {companyCd ? <Lines companyCd={companyCd}/> : ''}
    </>
  )
}

export default Companies

路線プルダウン

import React,{useState, useEffect} from 'react'
import Select from 'react-select'
import axios from 'axios'
import Stations from './Stations'

const Lines = (props) =>{
  const [lines, setLines] = useState([]);
  const [companyCd, setCompanyCd] = useState(0);
  const [lineCd, setLineCd] = useState(0);
  const [lineName, setLineName] = useState('');


  const getLines = async (companyCd) => {
    const result = await axios.get(`https://<Your Web Site URL>/backend/api/lines?company_cd=${companyCd}`)
      .then(res => {        
          if (res.data.length > 0){
          const lines = res.data[0].lines.map(line => {
            return { value: line.line_cd, label: line.line_name }
          })
          setLines(lines)
          setLineCd(0)
        }
    })
  }
  useEffect(() => {
    getLines(props.companyCd);
  },[]);


  useEffect(() => {
    if (props.companyCd !== companyCd){
      setCompanyCd(props.companyCd)
      getLines(props.companyCd)
      setLineCd(0)
      setLineName('路線を選択してください')      
    }
  });

  const changeLine = (e) =>{
    setLineCd(e.value)
    setLineName(e.label)
  }

  return (
    <>
      <Select options={lines} onChange={changeLine} value={{ value: lineCd, label: lineName }}/>
      {lineCd > 0 ? <Stations lineCd={lineCd}/> : ''}
    </>
  )
}

export default Lines

駅一覧

import React,{useState, useEffect} from 'react'
import axios from 'axios'

const Stations = (props) =>{
  const [stations, setStations] = useState([])
  const [lineCd, setLineCd] = useState(0)

  const getStatons = async (lineCd) => {
    const result = await axios.get(`https://<Your Web Site URL>/backend/api/stations?line_cd=${lineCd}`)
      .then(res => {
        if (res.data.length > 0){
          setStations(res.data)
        }
    })
  }
  useEffect(() => {
    getStatons(props.lineCd)
  },[]);

  useEffect(() => {
    console.log(`${props.lineCd} ${lineCd}`)
    if (props.lineCd !== lineCd){
      setLineCd(props.lineCd)
      getStatons(props.lineCd)   
    }
  });
    
  return (
    <>
      <h3>{stations ? '駅一覧' : ''}</h3>
      <ul>
        {stations ? 
            stations.map(station => {
                console.log(station)
                return (
                  <li>
                    {station.station_name}
                  </li>
                  );
            }) : 
            ''
        }
      </ul>
    </>
  )
}

export default Stations

実装結果

streamable.com