-
-
Notifications
You must be signed in to change notification settings - Fork 231
Different behavior compared to native react.js: state sudden reset #263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
They're different (hi btw) in that unlike the JS version, in your Scala version you're creating the component inside the tick-loop. Which means React keeps thinking it's got new components each tick. Move this: ReactComponentB[Int]("TextCounter")
.renderBackend[TextCounterBackend]
.build to the top level, outside of the loop. A common structure I use is to have an object with Props and/or State and/or Backend types defined inside, and a Like: object TextCounter {
type Props = Int
type State = Unit
final class Backend($: BackendScope[Props, State]) {
...
}
val Component = ...
} |
That was really fast and helpful 😄 Thanks a lot, let me try that. 👍 |
Unfortunately didn't work, still the same behavior. /* Scala */
// Just a plain Input object which saves user's input as a state
class InputBackend($: BackendScope[Unit, String]) {
def onChanged(e: ReactEventI): Callback ={
$.modState((_) => {e.target.value} );
}
def render() = {
<.input (
^.`type` := "text",
^.value := $.state.runNow(),
^.onChange ==> onChanged
);
}
}
// Displays a number and an <Input> next to it
class TextCounterBackend($: BackendScope[Int, Unit]) {
////// <--------- Moved this guy out from render()
val inputBuilder = ReactComponentB[Unit]("Input")
.initialState("this string wipes out any change in the input")
.renderBackend[InputBackend]
.build
def render() = {
<.div(
<.span($.props.runNow()),
inputBuilder(Unit)
);
}
}
var cnt = 0;
// Launch the counter
@JSExport
override def main(): Unit = {
////// <--------- Moved this guy out from setInterval()
var textCounterBuilder = ReactComponentB[Int]("TextCounter")
.renderBackend[TextCounterBackend]
.build;
setInterval(1000) {
ReactDOM.render(
textCounterBuilder(cnt),
dom.document.getElementById("test_javascript_scala")
);
cnt += 1;
};
} |
Try changing: def onChanged(e: ReactEventI): Callback ={
$.modState((_) => {e.target.value} );
} to def onChanged(e: ReactEventI): Callback =
$.setState(e.target.value) |
Yep, this works perfectly fine. Could you please explain what was the catch? |
@stillwaiting It was a case of #255. While we're here, there are a few small improvements to suggest. You can change def render() = {
<.input (
^.`type` := "text",
^.value := $.state.runNow(),
^.onChange ==> onChanged
);
} to def render(state: String) =
<.input.text(
^.value := state,
^.onChange ==> onChanged) and val inputBuilder = ReactComponentB[Unit]("Input")
.initialState("this string wipes out any change in the input")
.renderBackend[InputBackend]
.build
def render() = {
<.div(
<.span($.props.runNow()),
inputBuilder(Unit)
);
} to val inputBuilder = ReactComponentB[Unit]("Input")
.initialState("this string wipes out any change in the input")
.renderBackend[InputBackend]
.buildU // ← add U here because it's Unit. (This won't be needed from the next version onwards.)
def render(props: Int) =
<.div(
<.span(props),
inputBuilder()) |
Hi. I tried to translate this simple code into scalajs-react:
And the result:
However, the result in the browser behaves differently from the original one:
Am I doing something wrong here?
The text was updated successfully, but these errors were encountered: