国家冒険:私の最初の反応プロジェクト


私は、最終的にFlatironの第2段階で終わります.すべての段階の終わりに、我々は今までのすべての学習を包含するプロジェクトを作成しなければならなかった.最後の段階では、JavaScriptとAPIを組み込むプロジェクトを作成しました.この段階で、反応フレームワークの使い方を学びました.

私のプロジェクトで使用したもの

  • 反応フレームワーク

  • The National Park Service APIは、国立公園情報
  • を引っ張るのに用いられます

  • Weatherstack APIは、各々の国立公園
  • のために現在の天気を引くために使われます
  • Google Maps APIは、各々の国立公園
  • のためにキャンプ場を示すのに用いられます
  • JSONサーバは、この国立公園を保存するために、このプロジェクトで使用され
  • は、単一のページアプリ
  • でナビゲーションを作成するのに用いられるルータDOMを反応させます
    私のアプリスタイルに
  • 材料のUI

    プロジェクト概要


    パンデミックの間、すべてが閉じ始めたとき、私は自然でより多くの時間を過ごすことに興味を持ちました.私はずっとより多くの国立公園に行きたかったが、どこで出発するべきかについて、わかりませんでした.それを解決するために、私は州によって国立公園を検索することができます州の冒険のアプリを作成し、公園の概観を参照し、キャンプ場を表示します.

    国立公園を見る


    アプリの負荷、国立公園APIへの自動呼び出しが要求され、4つのランダムな国立公園がユーザーのために生成されるとき.これにより、フォームが使用される前にコンテンツが設定できます.

    //snippet of home component
     export class Home extends Component {
       state = {
           selectedParks: [],
           selectedState: null,
           defaultParks: [],
       }
    
       componentDidMount() {
           //fetch default parks
           fetch(`https://developer.nps.gov/api/v1/parks?api_key=${apiKey}&limit=50`)
           .then(response => response.json())
           .then(json => {
               const newArray = []
               for(let i = 0; i < 4; i++) {
                   newArray.push(json.data[Math.floor(Math.random()*json.data.length)])
               }
               this.setState({
               defaultParks: newArray,
               })
    
           })
       }
    
    -アプリのヒーローは、表示する状態を選択することができます制御フォームが含まれています.フォームが送信されると、状態は、国立公園APIへの別の要求を行うためにコールバック関数の親コンポーネントに戻されます.国立公園は、それぞれ自分のカードに人口があり、選択した状態がページタイトルに追加されます.

    //controlled form component
    export class Form extends Component {
       state = {
           stateAbbreviations: [
               'AL','AK','AS','AZ','AR','CA','CO','CT','DE','DC','FM','FL','GA',
               'GU','HI','ID','IL','IN','IA','KS','KY','LA','ME','MH','MD','MA',
               'MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND',
               'MP','OH','OK','OR','PW','PA','PR','RI','SC','SD','TN','TX','UT',
               'VT','VI','VA','WA','WV','WI','WY'
              ],
              selectedState: ""
       }
    
       handleChange = (event) => {
           this.setState({
               [event.target.name]: event.target.value
           })
       }
    
       handleSubmit = (event) => {
           event.preventDefault()
           this.props.fetchingParks(this.state.selectedState)
       }
    
    
       render() {
           return (
               <form className="hero-form" onSubmit={this.handleSubmit}>
                   <ButtonGroup>
                       <FormControl variant="outlined" color="secondary">
                           <InputLabel id="select-state">Select State</InputLabel>
                           <Select
                           labelId="select-state"
                           name="selectedState"
                           value={this.state.selectedState}
                           onChange={this.handleChange}
                           >
                               {
                               this.state.stateAbbreviations.map(state => (
                                   <MenuItem value={state} key={state}>{state}</MenuItem>
                               ))
                               }
                           </Select>
                       </FormControl>
    
                       <Button
                       type="submit"
                       variant="contained"
                       color="primary"
                       size="large"
                       >
                           Find Parks
                       </Button>
                   </ButtonGroup>
               </form>
           )
       }
    }
    
    //snippet of fetching Parks API from home component
    fetchParksApi = (stateAbbr = null) => {
           //fetch parks by state
           fetch(`https://developer.nps.gov/api/v1/parks?stateCode=${stateAbbr}=&api_key=${apiKey}`)
           .then(response => response.json())
           .then(json => {
             this.setState({
               selectedParks: json.data,
               selectedState: stateAbbr
             })
    
           })
         }
    

    国立公園の詳細を参照してください


    をクリックすると、国立公園についての概要ページに表示されます.あなたは公園、公園時間、公園の方向、入場料、活動、および現在の公園の天気についての情報が表示されます.

    -概要コンポーネントがレンダリングされると、APIの呼び出しは、公園のアドレスに基づいて現在の天気をプルするためにWeatherstack APIに行われます.ページの情報の残りは、国立公園サービスAPIから来ます.
    //API call for Weather
    export class ParkWeather extends Component {
       state = {
           temp: null,
           tempDetails: null
       }
    
       componentDidMount(){
           const validAddress = this.props.address.find(a => a.type === "Physical")
    
           fetch(`http://api.weatherstack.com/current?access_key=${apiKey}&units=f&query=${validAddress.postalCode}`)
           .then(res => res.json())
           .then(json => {
                this.setState({
                   temp: json.current.temperature,
                   tempDetails: json.current.weather_descriptions[0]
               })
           })
       }
    
    -ページのサブナビゲーション「キャンプ」リンクをクリックして、公園のキャンプ場を見ることができます.キャンプ構成要素がレンダリングされるとき、それは国立公園サービスAPIに別々の呼び出しを国立公園のためにキャンプ場で引っ張って、構成州に彼らを加えます.キャンプ場がない場合は、ミュート画面が表示されます.

    -キャンプ場がある場合は、GoogleマップAPIは、地図上にプロットされます.キャンプ場がクリックされると、キャンプ場情報が表示されます.これは、キャンプ場の説明、時間、コスト、予約ポリシー、および指示が含まれます.

    //camping component snippet
    export class ParkCamping extends Component {
       state = {
           campgrounds: [],
           selectedCampground: null
       }
    
       componentDidMount() {
    
           fetch(`https://developer.nps.gov/api/v1/campgrounds?parkCode=${this.props.parkcode}=&api_key=${apiKey}&limit=500`)
           .then(res => res.json())
           .then(json => {
               this.setState({
                   campgrounds: json.data
               })
           })
       }
    
       handleCampgroundClick = (campground) => {
           this.setState({
               selectedCampground: campground
           })
       }
    
       handleCampgroundWindowClick = () => {
           this.setState({
               selectedCampground: null
           })
       }
       render() {
           const height = document.getElementById('park-details').offsetHeight
    
           return (
               <>
               <Grid item
               xs={12} sm={12} md={this.state.selectedCampground ? 6 : 9}
               className="details-map">
            //Google API map
                   <CampingMap
                   longitude={parseInt(this.props.longitude)}
                   latitude={parseInt(this.props.latitude)}
                   campgrounds={this.state.campgrounds}
                   selectedCampground={this.state.selectedCampground}
                   handleCampgroundClick={this.handleCampgroundClick}
                   handleCampgroundWindowClick={this.handleCampgroundWindowClick}
                    />
               </Grid>
    
               {this.state.selectedCampground && (
                   <CampingInfo
                   height={height}
                   campground={this.state.selectedCampground}/>
               )}
               </>
           )
       }
    }
    

    国立公園の保存


    -あなたは国立公園のカードから直接、または概要ページ内の国立公園が好きです.あなたが公園のようなとき、それは州に追加され、好きな公園は、アプリケーションの変更と/またはリフレッシュ全体の持続するようにJSONサーバーに投稿されます.その後、あなたの“好きな公園”の下に表示されます.

    心が再びクリックされた場合、それは州から公園を削除し、JSONサーバーからそれを削除し、もはやあなたの

    //app component
      state = {
       savedParks: []
     }
    
    handleSaveParks = (newPark) => {
       const configData = {
         method: 'POST',
         headers: {
           'accept': 'application/json',
           'content-type': 'application/json'
         },
         body: JSON.stringify(newPark)
       }
    
       fetch('http://localhost:3000/parks', configData)
    
       this.setState(previousState => ({
         savedParks: [...previousState.savedParks, newPark]
       })
     )
     }
    
     handleUnsavePark = (removePark) => {
       const newSavedParks = this.state.savedParks.filter(park => park !== removePark)
    
       this.setState({
         savedParks: newSavedParks
       })
    
       fetch(`http://localhost:3000/parks/${removePark.id}`, {
         method: 'DELETE'
       })
     }
    
    //snippet of park card with like button
    <CardActions className="card-actions">
                       { parkIsSaved === undefined ?
                       <Tooltip title="Save Park" arrow>
                           <IconButton color="primary"
                           onClick={() => handleSaveParks(parkInfo)}
                           >
                               <FavoriteBorderIcon />
                           </IconButton>
                       </Tooltip>
                       :
                       <Tooltip title="Remove Park" arrow>
                       <IconButton color="primary"
                       onClick={() => handleUnsavePark(parkInfo)}
                       >
                           <FavoriteIcon />
                       </IconButton>
                       </Tooltip>
                       }
    
                       <Button
                       variant="text"
                       size="large"
                       color="primary"
                       endIcon={<TrendingFlatIcon />}
                       onClick={viewParkButtonClick}
                       >
                           View Park
                       </Button>
                   </CardActions>
    

    つのページのアプリでナビゲーションを作成する


    単一のページのアプリでは、その美しさは1つだけのページがすべての要素に人口があるです.ただし、ユーザーがURLを使用してサイトを移動することはできません.これは私が私の反応アプリ内のナビゲーションを構築するために反応ルータを使用している場所です.

    -私は、彼らが訪問しようとするURL経路にユーザーを指示するために、push()のResponse RouterのビルトインHistory法を利用しました.私は、主要なナビゲーションと概要サブナビゲーションでそれを使用しました.
    -組み込みの場所pathnameプロパティを使用して、どのページにユーザがいるかを表示します.現在のパスにマッチした場合、リンクのスタイルを変更するためにクラスにクラスを追加しました.

    -私はまた、必要に応じてユーザーがホームページや概要ページに簡単に戻ることができるように、公園の詳細ページにgoBack()の組み込みの歴史的方法を使用しました.

    最後の思考


    反応は、オブジェクト指向プログラミング(OOP)をよりよく理解するのを助けました.クラスのコンポーネントは、必要に応じて何度も使用することができますし、プロパティを持って自分の子供のコンポーネントに渡すことができるか、または状態として知られている個々の属性を運ぶ.反応がよりoopであるならば、それはより難問になっています、あるいは、現在フックで機能します.それにもかかわらず、私はフレームワークを学ぶ前に私がOOPを理解するのを助けました.
    私は楽しい時間を効率的に1つのページのアプリを構築する反応と材料のUIを学習した.それは私が私の最初のプロジェクトのために行ったようにスタイリングや関数の相互作用に焦点を当ててではなく、機能を構築するより多くの時間を与えた.私はこのビルドの反応クラスのコンポーネントに多くの焦点を当てたが、将来的に機能的なコンポーネントとフックを反応理解するより多くの時間を過ごしたい.