จะเชื่อมรายการเข้ากับอาร์เรย์สุดท้ายภายในอาร์เรย์รูทได้อย่างไร

โดยพื้นฐานแล้ว เมื่อฉันกดปุ่ม ฟังก์ชันของฉันจะเริ่มฟังการเปลี่ยนแปลงพิกัดและเชื่อมต่อข้อมูลที่รวบรวมใหม่เข้ากับอาร์เรย์

เมื่อกดปุ่มอีกครั้ง Listener จะถูกลบออก ผู้ใช้สามารถกดปุ่มและเริ่มฟังพิกัดชุดใหม่อีกครั้ง พวกเขาสามารถทำซ้ำได้

this.state = {
    pathArray: [], // originally a 1D array, should become 2D as user keep using the app
    pathCount: 0,
}

นี่คือลักษณะที่อาร์เรย์สุดท้ายควรมีลักษณะเพื่อให้ฉันสามารถดำเนินการส่วนการเรนเดอร์ต่อไปได้ ฉันต้องการที่จะสามารถสร้างดัชนีใหม่ในอาร์เรย์แบบไดนามิกเพื่อให้ข้อมูลใหม่ถูกผลักไปที่ด้านล่างของรายการ

ฉันจะสร้างอาร์เรย์ใหม่ภายในอาร์เรย์รูทได้อย่างไรเมื่อกดปุ่ม และต่อท้ายวัตถุในอาร์เรย์ลูกจนกว่าจะกดปุ่มอีกครั้ง หากกดปุ่มอีกครั้ง อาร์เรย์ลูกใหม่จะถูกสร้างขึ้นอีกครั้ง และกระบวนการจะดำเนินต่อไปเรื่อยๆ

pathArray = [
    [ 
        { lat: 0, long: 0 },
        { lat: 1, long: 2 },
    ],
    [ 
        { lat: 0, long: 0 },
        { lat: 1, long: 2 },
    ],
]

onButtonPressed = () => {
    const { running } = this.state
    if (!this.state.running) {
      this.followWatchCoords() // start collecting data
    } else {
      this.stopFollowing() //stop collecting data
    }
  }

followWatchCoords = () => {
    this.followUserWatchID = navigator.geolocation.watchPosition(({ coords }) => {
    
      this.calculateDistance(coords)

    }, null, GEOLOCATION_SETTINGS)
  }

calculateDistance = (coords) => {
    const { latitude, longitude } = coords

    const positionLatLong = pick(coords, ['latitude', 'longitude'])

    let newArr = this.state.pathArray.slice(); //copy array to mutate
    newArr.push(positionLatLong)


    this.setState({
      pathArray: newArr,
    })
  }


person J.Doe    schedule 30.05.2017    source แหล่งที่มา
comment
แล้วคำถามคืออะไร?   -  person Chris    schedule 30.05.2017
comment
ฉันจะสร้างอาร์เรย์ใหม่ภายในอาร์เรย์รูทได้อย่างไรเมื่อกดปุ่ม และต่อท้ายวัตถุในอาร์เรย์ลูกจนกว่าจะกดปุ่มอีกครั้ง หากกดปุ่มอีกครั้ง อาร์เรย์ลูกใหม่จะถูกสร้างขึ้นอีกครั้ง และกระบวนการจะดำเนินต่อไปเรื่อยๆ   -  person J.Doe    schedule 30.05.2017
comment
ปุ่มนี้กระตุ้นให้เกิดกระบวนการทำซ้ำโดยที่รายการจะเกิดขึ้นทุกๆ X วินาทีจนกระทั่งกดปุ่มอีกครั้งหรือไม่   -  person Chris    schedule 30.05.2017
comment
โดยพื้นฐานแล้ว ปุ่มจะเรียกใช้ฟังก์ชันอื่น (ตัวฟัง GPS) และนี่คือที่ที่ฉันจัดการอาร์เรย์ ใช่คุณเข้าใจแล้ว @Chris   -  person J.Doe    schedule 30.05.2017
comment
หากต้องการสร้างอาร์เรย์ใหม่ที่ท้ายรายการ: pathArray.push([]) หากต้องการผนวกองค์ประกอบในอาร์เรย์ที่สร้างขึ้นใหม่นี้: pathArray[pathArray.length - 1].push({lat: 1, long: 2})   -  person abhishekkannojia    schedule 30.05.2017
comment
@abhishekkannojia reactjs ไม่อนุญาตให้ฉันทำ pathArray[pathArray] ในบล็อก setState...   -  person J.Doe    schedule 30.05.2017


คำตอบ (2)


ด้านล่างนี้คือตัวอย่างง่ายๆ ของวิธีการนำสิ่งนี้ไปใช้

โดยพื้นฐานแล้วลำดับของเหตุการณ์คือ:

  1. การคลิกปุ่มจะเรียกใช้ฟังก์ชัน _startStop() ซึ่งจะเริ่มช่วงเวลาหนึ่ง
  2. ช่วงเวลาดึงพิกัดละติจูด/ลองจิจูดจาก GPS API ปลอมทุกๆ 3000 มิลลิวินาที
  3. พิกัดใหม่จะถูกผลักเข้าไปในอาร์เรย์สถานะ

หากคุณคลิกปุ่มอีกครั้ง ฟังก์ชันเดิมจะถูกเรียกใช้ แต่ช่วงเวลาจะถูกล้างและกระบวนการหยุดลง

class MyApp extends React.Component {
  constructor() {
    super();
    this.interval;
    this.state = {arr: []};
    this._getFakeCoords = this._getFakeCoords.bind(this);
    this._startStop = this._startStop.bind(this);
  }
  
  _getFakeCoords() {   
    return {lat: Math.random() * 100, long: Math.random() * 100};
  }
  
  _startStop() {
    if(this.interval) {
      clearInterval(this.interval);
      this.interval = null;
    } else {
      let newArr = this.state.arr.slice();  //copy the array so we can mutate it
      this.interval = setInterval(() => {
        newArr.push([this._getFakeCoords(), this._getFakeCoords()]);
        this.setState({arr: newArr});  //replace the old array with the mutated one
        console.log(newArr);  //preview the result
      }, 3000);
    }
  }
  
  render() {
    return (
      <div>
      	<button onClick={this._startStop}>Start/Stop</button>
      </div>
    );
  }
}

ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

person Chris    schedule 30.05.2017
comment
ดูเหมือนทำได้แต่มี 2 อย่าง ขั้นแรก ไลบรารีตำแหน่งทางภูมิศาสตร์จะเผยแพร่ข้อมูลใหม่ทุกๆ สองสามมิลลิวินาที ดังนั้นฟังก์ชัน setInterval อาจไม่มีประโยชน์ที่นี่ ส่วนประกอบที่ฉันใช้เรนเดอร์บรรทัดต้องใช้ 1 อาร์เรย์ของอ็อบเจ็กต์เพื่อเรนเดอร์ 1 บรรทัด 2 object = 1 บรรทัด, หลาย object (ใน 1 array) = 1 บรรทัดที่ยาวมาก ตามหลักการแล้ว หาก pathArray ของฉันมีอาร์เรย์ย่อย 2 รายการ เราก็ควรจะคาดหวังให้มี 2 บรรทัด - person J.Doe; 30.05.2017
comment
เพิ่งลองใช้วิธีการของคุณแต่มันไม่ตรงกับความต้องการของฉัน ฮ่าๆ ให้ฉันอัปเดตโพสต์ด้วยโค้ดปัจจุบันของฉัน - person J.Doe; 30.05.2017
comment
@ J.Doe โอเค แต่นี่เป็นเพียงการพิสูจน์แนวคิด ไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์ หาก API ของคุณทำงานแตกต่างออกไป ให้แก้ไขโค้ดตามนั้น ฉันเดาว่าคำถามที่นี่จะเป็นวิธีการแปลงอาร์เรย์หรืออะไรก็ตาม เพียงอัปเดตส่วนนั้น เช่น ในตอนแรกอาร์เรย์จะมีลักษณะอย่างไร และผลลัพธ์ควรเป็นอย่างไร ฉันจะอัปเดตเฉพาะส่วนนั้นเท่านั้น - person Chris; 30.05.2017
comment
ฉันได้อัปเดตโพสต์ด้วยโค้ดของฉันแล้ว เนื่องจากคุณจะเห็นได้ว่าฟังก์ชันการคำนวณระยะทางจะได้รับการอัปเดตทุกครั้งที่ไลบรารีการระบุตำแหน่งทางภูมิศาสตร์รวบรวมข้อมูลใหม่ - person J.Doe; 30.05.2017
comment
@J.Doe โอเค ฉันไม่เห็นส่วนที่มีปัญหาอาร์เรย์ 1D - › 2D นั่นคือปัญหาที่นี่ใช่ไหม - person Chris; 30.05.2017
comment
ฮ่าฮ่า เพื่อน CalculatorDistance อาจถูกดำเนินการหลายพันครั้งสำหรับทุกเซสชันของปุ่ม เคล็ดลับสำหรับปัญหานี้คือ ข้อมูลใหม่จะถูกเพิ่มที่ด้านล่างของรายการเสมอ ดังนั้นบางทีเราอาจสร้าง array ว่างได้เมื่อกดปุ่มครั้งแรก แล้วจึงผนวกข้อมูลเข้าไปใน child ตัวสุดท้ายของ array ?? อืม - person J.Doe; 30.05.2017
comment
@ J.Doe คุณอธิบายปัญหาของคุณได้ไม่ดีและคุณมีโค้ดจำนวนมากที่ไม่เกี่ยวข้องกับปัญหาการเขียนโปรแกรมที่คุณถาม ทำให้ผู้อื่นติดตามได้ยากเพราะคุณกำลังอธิบายแอปทั้งหมดของคุณมากกว่าปัญหาเฉพาะ... อย่างไรก็ตาม ถ้าฉันเข้าใจถูกต้อง คุณอาจใช้อาร์เรย์สองตัว - ตัวหนึ่งสำหรับ pathArray และอีกตัว tempArray tempArray เริ่มเติมข้อมูลด้วยพิกัดเมื่อคุณคลิกปุ่มเพื่อเริ่มต้น และเมื่อคุณหยุด คุณจะกด tempArray ลงใน pathArray? - person Chris; 30.05.2017
comment
ฉันยอมรับคำวิจารณ์ของคุณและจะแก้ไขปัญหาการจัดส่งของฉัน ส่วนประกอบของฉันควรเข้าถึง childArray ตัวสุดท้ายแบบเรียลไทม์ ดังนั้นหากเรากด tempArray เข้าไปใน pathArray หลังจากที่กดปุ่มอีกครั้งเท่านั้น จุดนั้นก็จะขาดหายไปเพราะแอปของฉันต้องวาดเส้นทางแบบเรียลไทม์ :( - person J.Doe; 30.05.2017
comment
ดูเหมือนว่าตรรกะจะถูกต้อง แต่เมื่อฉันพุชอาร์เรย์ใหม่ มันจะส่งคืนดัชนีเป็น 1 จากนั้นฉันพยายามพุชข้อมูลลงในอาร์เรย์ มันแสดง 'ไม่สามารถอ่านคุณสมบัติ 'พุช' ของไม่ได้กำหนด' - person J.Doe; 30.05.2017
comment
ให้เราสนทนาต่อในการแชท - person Chris; 30.05.2017

ในที่สุดก็แยกออกตามคำแนะนำที่เป็นประโยชน์ของคริส

ในฟังก์ชันปุ่มของฉัน ฉันจะสร้างอาร์เรย์ลูกใหม่ทุกครั้งที่มีการเรียก

this.setState({
    routeCoordinates: this.state.routeCoordinates.concat([[]]), //add array
    routeCount: this.state.routeCount + 1
})

ยังเพิ่ม routeCount หนึ่งทุกครั้งที่กดปุ่ม (เริ่มแรก -1 เนื่องจากลักษณะของอาเรย์)

จากนั้นในตัวฟัง GPS เนื่องจากฟังก์ชันการคำนวณระยะทางจะถูกเรียกใช้ทุกครั้งที่มีข้อมูลใหม่เข้ามาเราจึงต้องทำดังนี้

let newArr = [...routeCoordinates]
newArr[routeCount].push(positionLatLong)

this.setState({ routeCoordinates: newArr })

เคล็ดลับคือการใช้ concat และดันอย่างชาญฉลาด

person J.Doe    schedule 30.05.2017
comment
ดีใจที่คุณคิดวิธีแก้ปัญหาได้ คุณควรยอมรับคำตอบของคุณเองและพิจารณาการโหวตของฉันหากคุณพบว่ามีประโยชน์ ขอบคุณ. - person Chris; 31.05.2017
comment
แน่นอน! จะยอมรับคำตอบของฉันหลังจาก 2 วัน (ข้อจำกัดของ SO) - person J.Doe; 31.05.2017