Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React generated button on my form keeps refreshing the page

I was trying to make a chat application using node.js and react.js, but I cannot get past this issue where every time I click my page's button it refreshes the page. I'm fairly new to web development so forgive me if my issue is extremely obvious. My code can be found below:

// 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')
);

Here is the relevant HTML:

<!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>

For some reason the alert in my submit function is never reached. It just refreshes the page whenever I hit the button. I'm not sure whether this is an issue with React, jQuery, or just some odd thing that I missed with my HTML. I already tried using 'onsubmit = "return false"' in my button and preventDefault() as well but was still unable to pinpoint the problem. How do I fix my page's behavior, and what tools might I consider using to analyze this issue more closely?

like image 946
GenericAlias Avatar asked Jun 25 '15 00:06

GenericAlias


People also ask

How do I stop the button from refreshing the page React?

Use the preventDefault() method on the event object to prevent a page refresh on form submit in React, e.g. event. preventDefault() . The preventDefault method prevents the browser from issuing the default action which in the case of a form submission is to refresh the page.

How do you handle refresh in React?

To detect page refresh by pressing F5 in a React component, we can use the performance. navigation. type property to check what kind of navigation is done. If the value is 1, then we refreshed the page manually with the F5 key.

How do you refresh a page after submitting a form in React?

import React from 'react'; function App() { function refreshPage() { window. location. reload(false); } return ( <div> <button onClick={refreshPage}>Click to reload!

Does React redirect refresh page?

react-router-dom allows us to navigate through different pages on our app with/without refreshing the entire component. By default, BrowserRouter in react-router-dom will not refresh the entire page.


2 Answers

This is default HTML behavior. Buttons are submit buttons by default, so clicking them will submit the form. If you don't want that, then make it a "dumb" button:

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

You could also simply remove the <form> element since you don't seem to do anything with it.


The other issue is, as explained in the other answer, that you are trying to bind the event handler before the button exists.

The way you mix jQuery and React is messy, makes your code harder to maintain and harder to reason about. Just keep everything inside the React component:

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>
        );
    }
});

Similarly, messageData should be part of the state of the component, but I leave the conversion up to you.

Basically the way you use React currently doesn't give you much benefit. I recommend to read more of the React documentation, especially Thinking in React and Interactivity and Dynamic UIs.

like image 88
Felix Kling Avatar answered Sep 21 '22 16:09

Felix Kling


Sounds to me like a delegation issue - I'll bet #chat isn't in the DOM when you are creating the submit handler.

Try delegating the submit to the document (and preventing the default action):

$(document).on('submit','#chat',function(e) {
 e.preventDefault();
 ...
});
like image 42
Adam Avatar answered Sep 20 '22 16:09

Adam