Open hennoxlane opened 8 years ago
If you look at the code, it does make use of the Blaze APIs, so I don't think you can just drop it in React like that.
Here a copy and paste from my AceEditor React component.
// AceEditor.js
AceEditor = React.createClass({
getInitialState(){
return {
doc: null,
editor: null
}
},
componentDidMount(){
// Get Ace Editor from DOM
this.state.editor = ace.edit("editor");
// Set Ace Editor behaviour
this.setTheme('ace/theme/chrome');
this.state.editor.getSession().setMode("ace/mode/python");
this.state.editor.setFontSize(14);
this.state.editor.setShowPrintMargin(false);
this.state.editor.getSession().setUseWrapMode(true);
this.state.editor.$blockScrolling = Infinity;
this.state.editor.resize();
this.onChange();
},
shouldComponentUpdate(nextProps, nextState) {
return nextProps.docid !== this.props.docid;
},
componentDidUpdate(){
this.onChange();
},
componentWillUnmount(){
// Disconnect from ShareJS
this.disconnect();
// Clean up Ace memory to avoid memory leaks
this.state.editor.destroy();
},
// ------- ShareJS
onChange(){
// Doesn't have a document opened but wants to connect
if(!this.isConnected() && this.props.docid){
this.connect(this.props.docid);
}
// Has a document opened but wants to open a new document
if(this.isConnected() && this.props.docid){
this.disconnect();
this.connect(this.props.docid);
}
// Has a document opened but wants to close it
if(this.isConnected() && !this.props.docid){
this.disconnect();
}
},
connect(documentId){
let self = this;
if(this.isConnected()){
throw new Error('Already connected to ShareJS');
}
// Open the document
sharejs.open(documentId, 'text', function(error, doc){
if(error) {
console.error("Connection error:", error);
}else{
// Update state
self.setState({ doc: doc });
// Check we are connected
if(self.isConnected()){
// Attach ace editor to document
doc.attach_ace(self.state.editor);
console.log('Opened document [',documentId,']');
}else{
console.error("Document was opened but closed right away");
}
}
});
},
disconnect(){
if(this.isConnected()){
let name = this.state.doc.name;
this.state.doc.close();
if(this.state.doc.state === 'closed'){
console.log('Closed document [',name,']');
}else{
console.error('Failed to close document [',name,']');
}
this.state.doc.detach_ace();
}
},
isConnected(){
return this.state.doc != null && this.state.doc.state === 'open';
},
// ------- End of ShareJS
// ------- Editor State
setTheme(theme){
this.state.editor.setTheme(theme);
},
getAceInstance(){
return this.state.editor;
},
getText(){
return this.state.editor ? this.state.editor.getValue() : null;
},
// ------- End of Editor State
render() {
return (
<div id='editor' ref="editor" data-doc={this.props.docid} className="shareJSAce"></div>
)
}
});
And you can use it like this:
EditorPage = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
return {
currentUser: Meteor.user(),
document: Documents.findOne({_id: this.props.docId})
}
},
ready(){
return this.data.document;
},
render(){
return (
<Row class="container-fluid">
<div className="col-xs-12">
{this.ready() ? (
<AceEditor ref="editor" docid={this.props.docId}/>
) : null}
</div>
</Row>
)
}
});
I'm trying to use this template with ReactJS, by wrapping it in the blazetoreact package and rendering it that way.
I've got a documents collection, and am passing the mongo ID to docid. Here's the component I'm using shareJS in:
The result is that once I click a button (other component) to insert a new document, I'm seeing a textarea rendered, with '....loading' in it. And that's it. No functionality.
Troubleshooting: I can see the ops collection being created in my mongo, but there's no sign of the docs collection.
I've been able to setup shareJS with blaze just fine, no issues there: a click on a button creates a new Document, set the id to docid on a Session variable & presto, I can see the docs collection getting created in mongo & I'm good to go.
So far, that seems to be the one thing that's different: I'm not using Session in React.
So I'm wondering: does this package depend on usage of Session? Or is there another way to trigger the creation of the shareJS docs collection?
If there's no way to use this in Meteor + React, I'll use the plugin as is in a Blaze template, but I'd rather stick to a uniform codebase, if I can.
update: I've tried setting the document on a session variables and passing that through the docid prop, but no luck so far. This is most likely something to do with data-context not begin set correctly, I guess?