web-dev-qa-db-fra.com

Le bouton Réagir généré sur mon formulaire continue d'actualiser la page

J'essayais de créer une application de discussion à l'aide de node.js et de react.js, mais je ne parviens pas à surmonter ce problème. Chaque fois que je clique sur le bouton de ma page, la page est actualisée. Je suis assez nouveau dans le développement Web, alors pardonnez-moi si mon problème est extrêmement évident. Mon code peut être trouvé ci-dessous:

// Array of messages to be rendered
messageArray = [];
var socket = io();
// Prompt the user for their username
var user = Prompt("Please enter your name", "Anonymous");
// Emit username information so that it can be kept track of
socket.emit('new user', user);


$('#chat').submit(function() {
    // When the user hits submit, create a message object with 
    // information about their name, time sent, message, and socket id.
    // The socket id will be filled on the server side
    alert("hey");
    var date = new Date();
    var message = user + " (" + date.toLocaleTimeString('en-US') + "): " + $('#m').val();
    var messageJSON = {text:message, username:user, id:"", time:date}
    socket.emit('chat message', messageJSON);
    // Reset the value field
    $('#m').val('');
    return false;
});

// On receiving a chat message, update messageArray and 
// rerender the ViewingBox
socket.on('chat message', function(messages){
    messageArray = [];
    for (var i = 0; i < messages.length; i++) {
        alert(messages[i].text)
        messageArray.Push(messages[i].text);
    }

    React.render(
        <ViewingBox />,
        document.getElementById('root')
    );
});

// ViewingBox holds the view of the page and is updated whenever
// a new message is received
var ViewingBox = React.createClass({
    render: function() {
        return (
            <div>
                <h2>Global Chat: Logged in as {user}</h2>

                <ul id="messages">
                    {messageArray.map(function(data, i) {
                        return (<li>{data}</li>)
                    })} 
                </ul>
                <form id="chat" action="#">
                    <input id="m" autoComplete = "off" />
                     /*
                     *
                     Button in question
                     *
                     */
                    <button>Send</button>
                </form>
            </div>
        );
    }
});


// Render the viewingBox when the page initially loads
React.render(
    <ViewingBox />,
    document.getElementById('root')
);

Voici le HTML pertinent:

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <div id="root"></div>
    <script src="https://fb.me/react-0.13.3.js"></script>
    <script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
    <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>  
    <script type="text/jsx" src="/reactclient.js"></script> 
  </body>
</html>

Pour une raison quelconque, l'alerte dans ma fonction d'envoi n'est jamais atteinte. Il suffit d'actualiser la page chaque fois que je frappe le bouton. Je ne suis pas sûr qu'il s'agisse d'un problème avec React, jQuery ou simplement d'une chose étrange que j'ai manquée avec mon code HTML. J'ai déjà essayé d'utiliser 'onsubmit = "return false"' dans mon bouton et preventDefault () également mais je n'ai toujours pas pu identifier le problème. Comment corriger le comportement de ma page et quels outils puis-je envisager d'utiliser pour analyser ce problème de plus près?

14
GenericAlias

Cela me semble être un problème de délégation - je parie que #chat n’est pas dans le DOM lorsque vous créez le gestionnaire de soumission.

Essayez de déléguer l'envoi au document (et en empêchant l'action par défaut):

$(document).on('submit','#chat',function(e) {
 e.preventDefault();
 ...
});
11
Adam

C'est le comportement HTML par défaut. Les boutons sont des boutons de soumission par défaut, donc cliquez dessus pour soumettre le formulaire. Si vous ne le souhaitez pas, faites-en un bouton "bête":

<button type="button">Send</button>

Vous pouvez également simplement supprimer l'élément <form> puisque vous ne semblez rien faire avec.


Comme expliqué dans l’autre réponse, l’autre problème est que vous essayez de lier le gestionnaire d’événements avant que le bouton n’existe.

La façon dont vous mélangez jQuery et React est désordonnée, ce qui rend votre code plus difficile à gérer et à raisonner. Il suffit de tout conserver dans le composant React:

var ViewingBox = React.createClass({
    getInitialState: function() {
        return {
            message: ''
        };
    },

    _onMessageChange: function(event) {
        this.setState({message: event.target.value});
    },

    _send: function() {
        var date = new Date();
        var message = user + " (" + date.toLocaleTimeString('en-US') + "): " + this.state.message;
        var messageJSON = {text:message, username:user, id:"", time:date}
        socket.emit('chat message', messageJSON);
        // Reset the value field
        this.setState({message: ''});
    },

    render: function() {
        return (
            <div>
                <h2>Global Chat: Logged in as {user}</h2>

                <ul id="messages">
                    {messageArray.map(function(data, i) {
                        return (<li>{data}</li>)
                    })} 
                </ul>
                <form id="chat" action="#">
                    <input
                        value={this.state.message}
                        onChange={this._onMessageChange}
                        autoComplete="off"
                    />
                    <button type="button" onClick={this._send}>Send</button>
                </form>
            </div>
        );
    }
});

De même, messageData devrait faire partie de l'état du composant, mais je vous laisse la conversion.

Fondamentalement, la façon dont vous utilisez React actuellement ne vous donne pas beaucoup d'avantages. Je recommande de lire davantage de la documentation React , en particulier Penser dans React et Interactivité et interfaces utilisateur dynamiques .

36
Felix Kling

Votre problème est lié aux composants contrôlés et non contrôlés de React. Dans composant non contrôlé: Si vous n’appelez pas de fonction de gestionnaire pour gérer la soumission OR Si vous ne désactivez pas le comportement par défaut du code HTML, le bouton Soumettre sera toujours géré par le DOM.

En composant contrôlé: une fonction de gestion se chargera de l'action lors de la soumission. Exemple pour composant contrôlé: 

handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    **event.preventDefault();**
  }

<form onSubmit={**this.handleSubmit**}>
    <label>
      Name:
      <input type="text" value={this.state.value} onChange={this.handleChange} />
    </label>
    <input type="submit" value="Submit" />
  </form>

La discussion détaillée est ici: https://facebook.github.io/react/docs/uncontrolled-components.htmlhttps://facebook.github.io/react/docs/ forms.html

1
Vish