score:6

Accepted answer

it would appear to be a bug (or at least an inconsistency) in reactstrap. with normal form and button elements, react consistently calls the handlers with no particular this value¹ (so in this example, since class code is always in strict mode, we see this set to undefined in the call):

class test extends react.component{
    constructor(props){
        super(props);
    }

    handleclick() {
        console.log(typeof this);
    }

    handlesubmit(e) {
        console.log(typeof this);
        e.preventdefault();
    }

    render(){
        return(
            <react.fragment>
                <form onsubmit={this.handlesubmit} >

                <input type="submit" name="submit" value="submit" />

                </form>

                <button type="button" name="butt1" onclick={this.handleclick}>click</button>
            </react.fragment>
        );
    }
}

reactdom.render(<test />, document.getelementbyid("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>


but i have read that this inside normal functions is resolved dynamically i.e. who called it.

that's incorrect. with normal functions and with methods, the value of this within the call is determined by the caller. so what i'm saying above is that react does one thing and reactstrap does something else.

you may be thinking of the dom and how it handles event handlers, which is different from both react and (apparently) reactstrap. the dom calls your handler with this set to the element the handler was attached to. so if you attach a handler to a button and the handler is a normal function or a method, this will refer to the button when the handler is called by the dom. it's just something the dom does. react doesn't. reactstrap apparently varies depending on what handler it is or what kind of element it is (which is likely a bug).

more about this in this question's answers and in this old post on my anemic little blog.


in a comment you've said:

one more thing that i want to ask is how to use your code without strict mode, because it doesn't specify strict mode to be used

there are two reasons the code in that example is in strict mode:

  1. as i mentioned earlier in the answer, it's inside a class construct. code inside class is always strict. (so is code in a javascript module.)
  2. it's using babel to transpile the jsx, and by default babel turns on strict mode in the code it outputs.

so to see what happens in loose mode, you'd have to not use a class (easy enough) and not use babel, or at least tell babel not to turn on strict mode. i don't know if there's a way to tell babel not to use strict mode in stack snippets (there is a way when you're using it in the real world), but fortunately, you don't have to use jsx with react, it's just convenient. you can use react.createelement directly:

const {createelement} = react;

function test() {
    function handleclick() {
        console.log(this === window);
    }

    function handlesubmit(e) {
        console.log(this === window);
        e.preventdefault();
    }

    return createelement(react.fragment, {
        children: [
            createelement("form", {
                onsubmit: handlesubmit,
                children: [
                    createelement("input", {
                        type: "submit",
                        name: "submit",
                        value: "submit"
                    })
                ]
            }),
            createelement("button", {
                type: "button",
                name: "butt1",
                onclick: handleclick,
                children: ["click"]
            })
        ]
    });
}

reactdom.render(createelement(test), document.getelementbyid("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

note that this in the callbacks is now the global this, because when you call a normal function or method with no particular this value in loose mode, this within the callback is the global this (window on browsers).


¹ that's even covered by react's event documentation, although what it actually says is that this will be undefined. that's only true in strict mode. it is, technically, possible — but not a good idea — to use react without using strict mode.


Related Query

More Query from same tag