---
# System prepended metadata

title: react porject

---

# react porject

# 問題待討論

1.分頁功能 
* 之前上網查到參考的分頁寫法不懂
* 分頁第一頁 active 效果有點不太懂傳參數的方式



2.localStorage 傳參數的部分不懂 ><

>ask:第 148 行為什麼是寫 checkMyList 而不是 setCheckMyList ?
>有點小小的不太瞭解為什麼第 148 行要撈出 index 值!?
![](https://i.imgur.com/tEI0zMe.png)


3.localStorage bug >Z 說不是 bug，user 不會從 localStorage 將資料刪除

我發現直接將 localStorage 的資料刪除， UI 不會更新，要重新整理才會更新
![](https://i.imgur.com/zpZvY94.png)

4.localStorage UI bug

照著之前那版修改，有的時候畫面還是會出現 紫色奇怪的樣式，後來回去看紫色樣式好像代表沒加入我的最愛加成功
![](https://i.imgur.com/0pXWuvU.png)

5.function 寫法不同

-方法1
```=js
// import React,{useState, useEffect} from "react";
import CardList from './CardList';


const CardsContent = () =>{
  return (
    <div className="main">
        <h2 className="title-main">請先選擇區域</h2>
        <ul className="list">
            <CardList/>
            <CardList/>
            <CardList/>
            <CardList/>
            <CardList/>
            <CardList/>
        </ul>
    </div>
  );
};



export default CardsContent;
```
-方法2

```=js
import React from "react";

function Header() {
    return (
        <div className="main">
        <h2 className="title-main">這是首頁</h2>
        </div>
    );
}

export default Header;
```

6.不太懂有的時候結構賦值到底要等於什麼，例如:在這邊 App.js 第 112 行為什麼要等於 state?

![](https://i.imgur.com/dlMeUMB.png)



7.Api 撈回來的資料 讓 每個卡片高度不一樣
![](https://i.imgur.com/IV0eLSE.png)

8.傳變數問題 (Router)


/


others:

>think:
>一開始 build 專案環境是否就要先直接拆 layout.header.footer.content (頁面內容)出來?還是先寫好功能在拆?
>
Shenny 專案進度回報: https://hackmd.io/h_0GyLXBQ7uXCIIj8D0M0g?both
Shenny 筆記 : https://hackmd.io/xG1tw_nER7Wu3xL1gbGYPQ?both
Shenny React-router:https://hackmd.io/RA8jaPzCToaf9MLaFSGdmA




---

# 將我的最愛景點存入 localstorge

## Card.js
```=Js
import React,{useState,useEffect} from "react";
import clock from '../images/icons_clock.png'
import pin from '../images/icons_pin.png'
import phone from '../images/icons_phone.png'
import tag from '../images/icons_tag.png'


const Card = (props) => {
  //isFavorite = true > add favorite already
  //isFavorite = false > haven't added in  favorite list
  const [isFavorite,setIsFavorite] = useState(false);//based localstorage
  
  useEffect(()=>{
    if(localStorage.getItem('myFavoirite')!== null){
        console.log('id',props.item.Id)
      let myFavoirite = JSON.parse(localStorage.getItem('myFavoirite'));
      let index = myFavoirite.indexOf(props.item.Id);
      console.log('index',index)

      if(index >=0)
       setIsFavorite(!isFavorite);
      
       
       console.log('isFavorite',isFavorite)
      
    }
  },[]);
 




  const onLikeClick=(e) =>{
    e.preventDefault()
    
    //1. check isFavorite 
    if (isFavorite === false) 
    {
      //2. change style
      //style
      e.target.textContent="favorite"
      //control data
      // console.log('id', e.target.parentNode.parentNode.parentNode.id)
      let currentId =  e.target.parentNode.parentNode.parentNode.id;
    
      if(localStorage.getItem('myFavoirite')!== null){
        
        let myFavoirite = JSON.parse(localStorage.getItem('myFavoirite'));
        if(currentId !=='')
          myFavoirite.push(currentId);
        localStorage.setItem('myFavoirite',JSON.stringify(myFavoirite));
      }else{
        let myFavoirite = [];
        if(currentId !=='')
          myFavoirite.push(currentId);
        localStorage.setItem('myFavoirite',JSON.stringify(myFavoirite));
      }
     
    } 
    else{
      //style
      e.target.textContent="favorite-border"
      //control data
      // console.log('id', e.target.parentNode.parentNode.parentNode.id)
      let currentId =  e.target.parentNode.parentNode.parentNode.id;
    
      if(localStorage.getItem('myFavoirite')!== null){
        
        let myFavoirite = JSON.parse(localStorage.getItem('myFavoirite'));
        if(currentId !==''){
          let index = myFavoirite.indexOf(currentId);
          myFavoirite.splice(index,1);
        }
         
        localStorage.setItem('myFavoirite',JSON.stringify(myFavoirite));
      }else{
        alert('程式有誤請聯絡管理員');
      }
    }
    

       
   
    //3. udate isFavorite
    setIsFavorite(!isFavorite);
    
 }
    
  const {item} =  props;

  return(
    <li className="list-card" id={item.Id}>
      <div className="img" style={{backgroundImage: `url(${item.Picture1})`}}>
      <a className="material-icons" onClick={onLikeClick} href="!#"><i>favorite_border</i>
      </a>
          <div className="img-title">
              <h3 className="title-24px">{item.Name}</h3>
              <p className="title-16px">{item.Zone}</p>
          </div>
      </div>
      <div className="content-card">
      {/* <a onClick={onLikeClick} href="#"><span className="circle"><i className="material-icons color like">favorite_border</i></span></a> */}
          <p><img src={clock}  alt="icon"/>{item.Opentime}</p>
          <p><img src={pin}  alt="icon"/>{item.Add}</p>
          <div className="card_down_area">
            <p><img src={phone}  alt="icon"/>{item.Tel}</p>
            <p><img src={tag}  alt="icon"/>{item.Ticketinfo}</p>
          </div>
      </div>
    </li>

  )
};
export default Card;
```
# 如何在return 在map裡面去做判斷
這個範例是印出每個景點的名字,不是今天改得物件
你要參考要記得不要照抄
```=Js
 {cards.map(function(card,index) {
            //取出index索引小於5的資料
            if(index < 5)
                return <ul className="list">{card.Name}</ul>
            else
                return null
                
             //或是使用三元表示式   
            //return index < 5 ? <ul className="list">{card.Name}</ul>: null
          
         })} 
```


# 使用props傳入物件至組建

### App.js
```=js
import './css/App.css';
import gotopIcon from './images/btn_goTop.png'
import List from './components/List';
import Dropdown from './components/Dropdown';
import Card from './components/Card';

import React, { useState,useEffect } from 'react';
const App = () => { 

    const [state,setState] = useState({
        items: [],
        error: null,
        isLoaded: false,
        itemZones:[]
    
      });
    //api
    useEffect(()=>{
        fetch( 'https://raw.githubusercontent.com/hexschool/KCGTravel/master/datastore_search.json',{method:"GET"})
          .then(res => res.json())
          .then(
            (data) => {
              setState({
                isLoaded: true,
                items: data.result.records,
                itemZones: data.result.records.map((item)=>(item.Zone)).filter(function(element, index, arr){
                    return arr.indexOf(element) === index;
                })
              });
            },
            (sError) => {
              setState({
                isLoaded: true,
                error:sError
              });
            }
          )
  },[]);


  return (

    <div className="App">
      <header className="banner">
        <div className="container">
            <h1>高雄旅遊資訊網</h1>
            <Dropdown itemZones= {state.itemZones}/> 
        
            <div className="menu">
                <p className="title-menu">熱門行政區</p>
                
                <List/>
            </div>
            <div className="icon-menu">
                <hr />
            </div> 
        </div>
    </header>
    <div className="content container"> 
        <div className="main">
            <h2>請先選擇區域</h2>
            
            <Card items={state.items}/>
       
        </div>
        <div className="goTop">
            <img src={gotopIcon}  alt="gotopIcon"/>
        </div>
       
        {/* <Pagination/> */}
        {/* <ul className="page">
           <li><a href="https://hackmd.io/xG1tw_nER7Wu3xL1gbGYPQ?both">Prev </a></li>
           <li><a href="#">1</a></li>
           <li><a href="#">2</a></li>
           <li><a href="#">Next</a></li>
        </ul> */}
    </div>
    
    <footer>
        <div className="container">
            <p>高雄旅遊網</p>
            <p className="pStyle">資料來源: 高雄市政府</p>
        </div>
    </footer>
    
    </div>
  );
}

export default App;

```

### dropdownlist.js
```=js
import React from 'react';


const Dropdown = (props) =>{
        let {itemZones} = props;
          return (
              <div>
                  <select>
                        <option selected disabled>--請選擇行政區--</option>
                        {itemZones.map((zone) =>(
                                <option value={zone}>{zone}</option>   
                            )
                        )}
                  </select>
              </div>
          );
      }


export default Dropdown;

```

### Card.js(先是示範只秀name)
```=js
import React, {} from 'react';

const Card = (props) =>{
    
    let {items} = props;
    return(
       
        <div> {items.map((item) =>(
            <p>{item.Name}</p>
            )
        )}</div>
    )
}

export default Card;
```


---

(下面是舊的略過...)

## hooks
```=js
// import React,{Component} from "react";
import React,{useState, useEffect} from "react";

const API = () =>{

  
  const [state,setState] = useState({
    items: [],
    error: null,
    isLoaded: false

  });
  

  useEffect(()=>{
        fetch( 'https://raw.githubusercontent.com/hexschool/KCGTravel/master/datastore_search.json',{method:"GET"})
          .then(res => res.json())
          .then(
            (data) => {
              setState({
                isLoaded: true,
                items: data.result.records
                
              });
            },
            (sError) => {
              setState({
                isLoaded: true,
                error:sError,
                items:null
              });
            }
          )
  },[]);


        const { error, isLoaded, items } = state;
        if (error) {
          return <div>Error: {error.message}</div>;
        } else if (!isLoaded) {
          return <div>Loading...</div>;
        } else {
          return (
            <ul>
              {items.map(item => (
                <p> {item.Name}</p>
              ))}
            </ul>
          );
        }
      }




// class API extends Component{
   
//     constructor(props) {
//         super(props);
//         this.state = {
//           error: null,
//           isLoaded: false,
//           items: []
//         };
//       }
    
//     componentDidMount() {
//         fetch( 'https://raw.githubusercontent.com/hexschool/KCGTravel/master/datastore_search.json',{method:"GET"})
//           .then(res => res.json())
//           .then(
//             (data) => {
//               this.setState({
//                 isLoaded: true,
//                 items: data.result.records
//               });
//             },
//             // Note: it's important to handle errors here
//             // instead of a catch() block so that we don't swallow
//             // exceptions from actual bugs in components.
//             (error) => {
//               this.setState({
//                 isLoaded: true,
//                 error
//               });
//             }
//           )
//       }

//       render() {
//         const { error, isLoaded, items } = this.state;
//         if (error) {
//           return <div>Error: {error.message}</div>;
//         } else if (!isLoaded) {
//           return <div>Loading...</div>;
//         } else {
//           return (
//             <ul>
//               {items.map(item => (
//                 <p> {item.Name}</p>
//               ))}
//             </ul>
//           );
//         }
//       }
// }

 export default API;
```


## API
```=react.js
import React,{Component} from "react";

class API extends Component{
   
    constructor(props) {
        super(props);
        this.state = {
          error: null,
          isLoaded: false,
          items: []
        };
      }
    
    componentDidMount() {
        fetch( 'https://raw.githubusercontent.com/hexschool/KCGTravel/master/datastore_search.json',{method:"GET"})
          .then(res => res.json())
          .then(
            (data) => {
              this.setState({
                isLoaded: true,
                items: data.result.records
              });
            },
            // Note: it's important to handle errors here
            // instead of a catch() block so that we don't swallow
            // exceptions from actual bugs in components.
            (error) => {
              this.setState({
                isLoaded: true,
                error
              });
            }
          )
      }

      render() {
        const { error, isLoaded, items } = this.state;
        if (error) {
          return <div>Error: {error.message}</div>;
        } else if (!isLoaded) {
          return <div>Loading...</div>;
        } else {
          return (
            <ul>
              {items.map(item => (
                <p> {item.Name}</p>
              ))}
            </ul>
          );
        }
      }
}

export default API;
```


## APP
```=react.js
import logo from './logo.svg';
import './App.css';
// import List from './List';
//API
import API from './testAPI';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
       <API/>
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

```