Open JeremyIglehart opened 7 years ago
Okay, figured it out (I think)
std:accounts-ui just doesn't maintain any kind of state. If react decides to re-render the form for any reason it totally kills <Accounts.ui.LoginForm />
. I'm not sure this is right - to me, a component should live on if things get re-rendered (who knows what else is going on where they get rendered). It should also maintain some kind of internal state. If the initial state was for signup, but somebody clicks login (and then something else re-renders in react) the form should just re-render right where you're at.
Weirdness.
Anyways, here's the code to test it to see what I'm talking about:
import React, { Component } from 'react'
import { Accounts, STATES } from 'meteor/std:accounts-ui';
class MyEditor extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<button onClick={() => this.forceUpdate()}>Rerender</button>
<Accounts.ui.LoginForm formState={STATES.SIGN_UP} />
</div>
)
}
}
export default MyEditor;
The code above always returns to the state passed to it in the props.
import React, { Component } from 'react'
import { Accounts, STATES } from 'meteor/std:accounts-ui';
class MyEditor extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<button onClick={() => this.forceUpdate()}>Rerender</button>
<Accounts.ui.LoginForm />
</div>
)
}
}
export default MyEditor;
This is even worse! because something re-renders the page, the whole form just vanishes for no reason.
So - This issue is closed, I'm going to investigate further and find out if there is a better way of maintaining state. If not, I'm going to post a feature request issue.
Thanks so much for your hard work!
Okay - no, something is really wrong here. Because if you force the state to be in sign-up mode the form doesn't respond to show that you're logged in when you're logged in.
If somebody could please take a look at this and explain, I would really appreciate it.
Thanks to Sean (arist0tl3) and his comment and his fork
It's interesting what he did there. Basically, I was calling <Accounts.ui.LoginForm />
from within the same "component" where the DraftJS <Editor />
component was called - like this:
// Imports
class MyEditor extends Component {
// Other component stuff
return (
<div className="editor-container">
<h1>DraftJS and Meteor Editor:</h1>
<IconButton onClick={this._onBoldClick.bind(this)} touch={true} tooltip="Format Bold" tooltipPosition="top-right">
<FontIcon className="material-icons" style={iconStyles}>format_bold</FontIcon>
</IconButton>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleKeyCommand={this.handleKeyCommand.bind(this)}
/>
<RaisedButton label="Log Editor State to Console" onClick={this.logState.bind(this)} primary={true} style={buttonStyle} />
</div>
<Accounts.ui.LoginForm />
<p>This is a test - do I stay?</p>
)
// Exports
and Sean tried taking <Accounts.ui.LoginForm />
and moving it into a different react component and then calling the two different components from a parent component. Here's what he did in code:
<Accounts.ui.LoginForm />
from <MyEditor />
// Imports
class MyEditor extends Component {
// Other component stuff
return (
<div className="editor-container">
<h1>DraftJS and Meteor Editor:</h1>
<IconButton onClick={this._onBoldClick.bind(this)} touch={true} tooltip="Format Bold" tooltipPosition="top-right">
<FontIcon className="material-icons" style={iconStyles}>format_bold</FontIcon>
</IconButton>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleKeyCommand={this.handleKeyCommand.bind(this)}
/>
<RaisedButton label="Log Editor State to Console" onClick={this.logState.bind(this)} primary={true} style={buttonStyle} />
</div>
)
// Exports
Created a <LogIn />
component:
// Imports
class LogIn extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div className="login-container">
<Accounts.ui.LoginForm />
<p>This is a test - do I stay?</p>
</div>
)
}
}
// Exports
Then called the two from a parent <Home />
component:
class Home extends Component {
render () {
return (
<div>
<MyEditor />
<LogIn />
</div>
)
}
}
I'm not actually sure why this works... but it does. It seams to me as though <Accounts.ui.LoginForm />
should be able to handle "re-rendering". I guess I just don't understand React well enough to understand why this separation is needed.
Is this a bug, or part of the intended design?
Is there come explanation of why this is the way it is that I should know?
Like, why is it normal that <Accounts.ui.LoginForm />
can't handle arbitrary re-renders without breaking?
To sweeten the deal a little bit - I've created a StackOverflow question to this extent. - Now it's worth points! :)
Is this still an issue, @JeremyIglehart?
I'm really not sure what is happening here. When I click on the "DraftJS" contentEditable - the
<Accounts.ui.LoginForm />
instantly disappears. I haven't the foggiest idea why.Demo:
To see the bug in its current state:
Go to: http://draftjsmeteor.autoschematic.com/
To duplicate the problem in your own development environment:
settings-development.json
file (you can leave it blank)npm start
The main question:
Does anyone know why DraftJS kills the
<Accounts.ui.LoginForm />
?After looking into this problem for two days now, I suspect the problem is hiding somewhere in how
<Accounts.ui.LoginForm />
is doing something - perhaps in their STATES API? I'm really confused here. Any help would really be appreciated.Problems I've ruled out:
Session Variable
problem. DraftJS doesn't use them - in fact, there are no Session Variables being used at all right now as far as I can detect (using Meteor Toys)<Accounts.ui.LoginForm />
component I have placed a regular vanilla<p>
tag and it is left alone.It doesn't seem to me this problem has anything to do with Meteor, or React specifically.
Where I'm looking now to solve this:
accounts-ui
is rendering just fine - after clicking in the DraftJS contentEditable area, however, something inside this component breaks.Issues Tracking this Bug:
I've created three issues to try and track this down:
Once I find a solution I'll update all of the issues, forums and questions I've posted everywhere.