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
Should manual request return promise? #19
Comments
You can read from PromiseState. It returns |
@ashtuchkin it will inject a PromiseState to whatever prop you assigned in updateData() inside of connect(). If you want to do something with that like show a user message, you'll need to check that it is both defined and fulfilled. It will be undefined until you call updateData(). Use componentWillReceiveProps() if you want to compare it to the current value, otherwise just use it in render(). |
I guess I can do that. Maybe we can do better though.. See my case of a simple edit page with a save button: @connect((props) => ({
project: `/api/projects/${props.id}`,
updateProject: (data) => ({
project: { url: `/api/projects/${props.id}`, method: "PATCH", body: data }
})
}))
class ProjectEditPage extends React.Component {
constructor(props) {
super()
// We don't have the data here as it's not loaded.
this.state = {}
}
componentWillReceiveProps(props) {
if (props.project.fulfilled) {
// When the project is loaded or updated, we set the state to new values.
this.setState({props.project.value})
// How do we notify user that save is successful? Is this even a good place?
}
}
// 200 lines here
saveProject() {
this.props.updateProject(this.state)
// isn't it a lot clearer to just add .then(() => flash("Save successful")) here?
}
render() {
if (this.props.project.pending)
return <Loading/>
if (this.props.project.rejected)
return <Error ... />
return <div>
Project name: <input value={this.state.name} onChange={..change this.state.name}/>
....other props...
<button onClick={()=>this.saveProject()}>Save project</button>
</div>
}
} |
You don't need to use state, you have two options: class ProjectEditPage extends React.Component {
saveProject() {
if (props.project.fulfilled) {
this.props.updateProject(props.project.value);
}
}
render() {
if (this.props.project.pending)
return <Loading/>
if (this.props.project.rejected)
return <Error ... />
return <div>
Project name: <input value={this.state.name} onChange={..change this.state.name}/>
....other props...
<button onClick={()=>this.saveProject()}>Save project</button>
</div>
}
} Or: class ProjectEditPage extends React.Component {
saveProject() {
this.props.updateProject(props.project.value);
}
render() {
if (this.props.project.pending)
return <Loading/>
if (this.props.project.rejected)
return <Error ... />
return <div>
Project name: <input value={this.state.name} onChange={..change this.state.name}/>
....other props...
{props.project.fulfilled && <button onClick={()=>this.saveProject()}>Save project</button>}
</div>
}
}
```jsx |
@hnordt not following you.. I need user to edit these inputs. those values are definitely state. Plus, where do I notify user that the save is successful? |
Here is my idea: @connect(({ id }) => ({
project: `/api/projects/${id}`,
updateProject: data => ({
project: { url: `/api/projects/${id}`, method: 'PATCH', body: data }
})
}))
class ProjectEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
project: null,
projectUpdated: null
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.project.fulfilled) {
this.setState({
project: nextProps.project.value,
projectUpdated: this.state.project.isDirty // if project was dirty, means it was updated
});
}
}
handleProjectChange(property, value) {
this.setState({
project: Object.assign({}, this.state.project, {
[property]: value,
isDirty: true
})
})
}
render() {
const {
project: {
pending: isPending,
rejected: isRejected
},
updateProject
} = this.props;
if (isPending) {
return <Spinner />;
}
if (isRejected) {
return <Error />;
}
const {
project,
projectUpdated
} = this.state;
return (
<div>
{projectUpdated && <strong>Updated!</strong>}
{project && (
<div>
Project name:
<br />
<input value={project.name} onChange={event => this.handleProjectChange('name', event.target.value)} />
<button onClick={() => updateProject(project)}>Save project</button>
</div>
)}
</div>
);
}
} |
So basically you propose to add an I still think returning a promise makes sense conceptually (as a signal that the action is done) and makes code cleaner/easier to follow. I do understand that extending api surface will require more maintenance though, so will not press. Thanks. |
@ashtuchkin am I wrong or we can make it work using
Have you also tried |
Yeah, but it's has different semantics. |
@ryanbrainard if we have I agree with @ashtuchkin, returning a promise is helpful. |
Sorry for the delay. I didn't see these comments because they were on a closed issue. Although it wasn't really designed for it, you could try to use @connect((props) => ({
project: `/api/projects/${props.id}`,
updateProject: (data) => ({
project: {
url: `/api/projects/${props.id}`,
method: "PATCH",
body: data,
andThen: () => {
// do something here
return {}
}
}
})
})) This is kind of crappy because now there is a side effect, but since it is inside of a fetch function, I guess it is less bad. The other problem is that you probably don't have access to whatever you want to call here either. If we add "identity requests", they could actually work quite well here too, so you could do something like this: @connect((props) => ({
project: `/api/projects/${props.id}`,
updateProject: (data) => ({
project: {
url: `/api/projects/${props.id}`,
method: "PATCH",
body: data,
andThen: () => ({
projectUpdated: {
value: true // some static value of your choice
}
})
}
})
})) Then you'd get Going to re-open this so I see the comments. |
Closing this to be implemented at identity requests in #33. Re-open if there is more discussion to be had. |
When doing requests from event handlers, I wanted to be notified when request finishes, so that I could show message to the user. Like this:
I'm not sure what value should be passed to the promise though.
The text was updated successfully, but these errors were encountered: