2017-07-06 6 views
1

Ich habe eine Methode, die ein Symbol (font-awesome-Symbol) in bereitgestellten Container rendert. Icon-Rendering kann passieren, indem der Benutzer auf bestimmte div oder durch Programm selbst aufruft, die Rendering-Funktion automatisch aufruft, wenn es den Benutzer nachahmt, der auf ein bestimmtes div klickt.ReactDOM.render hat unter bestimmten Umständen keine Wirkung?

Um dies besser zu verstehen. Ich habe dieses so genannte TicTacToe Spiel erstellt. Es ist möglich, player vs player oder player vs cpu zu spielen. Wenn zwei Spieler spielen, gibt es kein Problem, alles wird gut wiedergegeben.

Wenn nun ein Spieler gegen die CPU spielt, passiert etwas Seltsames. Wenn der erste Spieler eine CPU ist, wird seine erste Bewegung nicht wiedergegeben (das Symbol erscheint nicht). Aber der Rest scheint in Ordnung zu sein.

Und wenn ich beide Spieler zu CPU machen (CPU spielt gegen eine andere CPU), dann wird nichts gerendert. Könnte es sein, dass ReactDOM.render Änderungen ignoriert, wenn sie zu schnell passieren ?;)

hier also ein Teil des Programms (Spiel):

$(document).ready(function() { 
    const ICONS_CLASSES = { 
     x: 'fa fa-times fa-lg', 
     o: 'fa fa-circle-o fa-5x' 
    } 
    function renderMove(el, turn){ 
     const classes = ICONS_CLASSES[turn]; 
     ReactDOM.render(
      React.createElement('span', {'className': classes}), 
      el 
     ) 
    } 
... 
... 
}); 

Auch hier ist eine Funktion, die durch das Programm selbst aufgerufen wird, zu imitieren Klick auf einen bestimmten div in einem Spiel (let CPU gut sagen „klickt“ it):

function clickPosition(el, tic){ 
    if(tic.state == 'running'){ 
     // Save which player played, because after playing move, it will 
     // switch turn for another player. 
     const type = tic.turn.type; 
     const res = tic.play(el.id); 
     if(res != 'invalid') 
      renderMove(el, type); 
     updateInfo(tic.info) 
     // Add start block to be able to play again. 
     if(tic.state == 'stopped'){ 
      // Highlight win combo if there is any 
      if(tic.winCombo) 
       highlightWin(tic.winCombo) 
      toggleEl($('#start')) 
     } 

    } 
} 

wie zuvor so fordern solche machen die wird nicht die ganze Zeit machen (wenn sie mit CPU spielen).

Aber wenn ich das dies machen zu ändern:

el.innerHTML = `<span class="${classes}"></span>`; 

Dann macht es ein Symbol nur in Ordnung. Egal, ob das Spiel gespielt wird player vs player, cpu vs player, player vs cpu oder sogar cpu vs cpu (in diesem Fall werden alle Symbole sofort gerendert, weil das Endergebnis immer gezeichnet wird).

Gibt es ein Problem mit ReactDOM.render?

P.S. Wenn Sie interessiert sind, können Sie hier den vollständigen Code finden (derzeit ist es möglich, cpu vs player gespielt zu werden, was bedeutet, dass zuerst die CPU gespielt wird. Und weil es mit ReactDOM.render rendert, wird der erste Zug unsichtbar sein. Andere sollten in Ordnung sein): https://codepen.io/andriusl/pen/qjyBdB

Antwort

1

Es sieht aus wie alles ist in Ordnung mit ReactDOM.render. Aber ich hatte recht mit der Annahme, dass Rendering zu schnell abläuft. Aber von einem anderen Ort.

Es gab eine Funktion (die ich in Frage nicht erwähnt habe), die alle gerenderten Symbole löschte. Und es würde nach dem Start des Spiels klar sein. Wenn Spieler spielen, dann gibt es kein Problem, da das Löschen später erfolgt, klickt der Benutzer auf div. Aber wenn CPU das macht, macht es viel schneller, so dass es an der Reihe ist, bevor das Aufräumen aufgerufen wird und es das Bewegungssymbol löscht.

Technisch gesehen ist es gemacht, aber es sofort entfernt wird, die aussehen wie es nie gemacht wurde, zumindest für uns Menschen :)

So war fix ReactDOM.unmountComponentAtNode vor tic.start zu bewegen. Dann wird es immer gelöscht, bevor das Spiel gestartet wird, nicht danach (oder bevor ein anderes Spiel gestartet wird).

$('#x, #o').on('click', function() { 
    const second = {'x': 'o', 'o': 'x'}; 
    // Clear filled positions if any. 
    let positions = document.getElementsByClassName('pos'); 
    _.each(positions, pos => { 
     ReactDOM.unmountComponentAtNode(pos); 
    }) 
    tic.start(this.id, second[this.id]); 
    toggleEl($('#start')); 
    updateInfo(tic.info); 

}) 
+0

Vielen Dank für Ihre Lösung.Ich bin heute Morgen über deine Frage gestolpert, aber ich hatte keine Zeit, wirklich darüber nachzudenken. Ich muss sagen, dass Sie wahrscheinlich die * beste * Verwendung hier nicht ausnutzen (mit geschachtelten Komponenten, Status, Requisiten, Event-Listenern und reagieren lassen), aber ich fand Ihren Ansatz sehr interessant (im richtigen Sinne). :) – DonovanM

Verwandte Themen