Redux thunk 在下一个动作之前未解析 + then 不是函数或分派未定义
Redux thunk not resolving before next action + then is not a function or dispatch undefined
一直在开发 react/redux 应用程序,为此我一直在用头撞墙。
问题 - 我正在使用 wzywyg 编辑器更新文件。当我上传照片时,应用程序会尝试在操作完成图像处理之前插入图像。因此,导致 image url 未定义。当我上传第二张图片时,第一张图片被插入等等。
很明显,thunk 在调用下一个操作之前没有解析。
更多详情
- 我的应用程序中有一个文本编辑器 (summernote-react)。当用户上传图片时,onImageUpload 触发并触发 handleImageUpload。
- 从那里,我通过 mapStatetoProps 发送一个动作,并处理图像以供上传。
- 图片处理完成后,应该return到编辑器,并将图片路径嵌入编辑器进行预览。
现在,我遇到了关于 dispatch 未定义的相同错误模式,然后不是函数。我错过了什么?
addUploadToDocument(...).then is not a function
Uncaught TypeError: Cannot read property 'then' of undefined
我可以确认以下内容:
- Redux-thunk 设置正确。它在我们的生产版本中工作并启动。
- 正在从我的组件调用该操作。只是不确定是否派送。我可以成功上传图片,但在操作解决之前发起了回调。
这是我的操作代码:
// actions.js
// thunk
export function loadImage(document, file) {
return (dispatch, getState) => {
return dispatch(addUploadToDocument(document, file))
.then(() => {
console.log('Thunk is loaded.. chyeah.');
var uploads = this.props.uploads
var image = uploads[uploads.length - 1]
ReactSummernote.insertImage(image.previewURL, $image => {
$image.css("width", Math.floor($image.width() / 2));
$image.attr("alt", image.name);
});
});
}
}
//image processing action
export function addUploadToDocument(document, file) {
return (dispatch, getState) => {
//const position = getState().bodyEditorSelection.index
const base64Reader = new FileReader()
base64Reader.addEventListener('load', function() {
const base64 = base64Reader.result.replace(/data:.*?base64,/, '')
const key = Math.random().toString(36).substring(7)
const destination_path = `/uploads/${document.name}/${key}-${file.name}`
return dispatch({
type: DOCUMENT_ADD_UPLOAD,
payload: {
path: destination_path,
type: file.type,
base64: base64,
name: document.name,
previewURL: window.URL.createObjectURL(file),
//position: position
}
})
})
base64Reader.readAsDataURL(file)
}
}
这是我的组件。
handleImageUpload (files, editor, welEditable) {
var file = files[files.length -1];
this.props.loadImage(this.props.document, file)
}
render() {
this.syncBodyEditorState()
this.state = this.state || {}
return (
<ReactSummernote
value={this.props.body}
options={{
height: 750,
dialogsInBody: true,
toolbar: [
["style", ["style"]],
["font", ["bold", "underline", "clear"]],
["fontname", ["fontname"]],
["para", ["ul", "ol", "paragraph"]],
["table", ["table"]],
["insert", ["link", "picture", "video"]],
["view", ["codeview"]]
]
}}
onImageUpload={this.handleImageUpload}
onChange={this.handleChange}
/>
)
}
}
function mapStateToProperties(state) {
const currentDocument = currentDocumentSelector(state).currentDocument
return {
document: currentDocument,
bodyEditorSelection: state.bodyEditorSelection,
body: currentDocument.content.body,
uploads: currentDocument.content.uploads
}
}
export default connect(mapStateToProperties, {
SummernoteEditor,
updateDocumentBody,
updateBodyEditorSelection,
addUploadToDocument,
loadImage
})(SummernoteEditor)
我是不是遗漏了一些微不足道的东西?我看了几十个例子,砰的一声把我难住了!
在此先感谢您的帮助。
现在你的 addUploadToDocument
函数没有 return 承诺,尽管如此你 .then
你的 dispatch
方法(而且它只是一个 thunk returns 一个普通对象)。如果你需要继续,你可以将 addUploadToDocument
函数的内容包装在一个 promise 中,然后它就可以了。这里有一些不同的方法,通过一些折射来帮助您入门(假设 'load' 事件只能发生一次):
export function loadImage(document, file) {
return (dispatch, getState) => {
const base64Reader = new FileReader();
const promise = new Promise((resolve, reject)=> {
base64Reader.addEventListener('load', resolve)
})
.then(()=> {
const base64 = base64Reader.result.replace(/data:.*?base64,/, '')
const key = Math.random().toString(36).substring(7)
const destination_path = `/uploads/${document.name}/${key}-${file.name}`
dispatch({
type: DOCUMENT_ADD_UPLOAD,
payload: {
path: destination_path,
type: file.type,
base64: base64,
name: document.name,
previewURL: window.URL.createObjectURL(file),
//position: position
}
})
})
.then(()=> {
console.log('Thunk is loaded.. chyeah.');
var uploads = this.props.uploads
var image = uploads[uploads.length - 1]
ReactSummernote.insertImage(image.previewURL, $image => {
$image.css("width", Math.floor($image.width() / 2));
$image.attr("alt", image.name);
});
})
base64Reader.readAsDataURL(file);
return promise;
}
}
一直在开发 react/redux 应用程序,为此我一直在用头撞墙。
问题 - 我正在使用 wzywyg 编辑器更新文件。当我上传照片时,应用程序会尝试在操作完成图像处理之前插入图像。因此,导致 image url 未定义。当我上传第二张图片时,第一张图片被插入等等。
很明显,thunk 在调用下一个操作之前没有解析。
更多详情
- 我的应用程序中有一个文本编辑器 (summernote-react)。当用户上传图片时,onImageUpload 触发并触发 handleImageUpload。
- 从那里,我通过 mapStatetoProps 发送一个动作,并处理图像以供上传。
- 图片处理完成后,应该return到编辑器,并将图片路径嵌入编辑器进行预览。
现在,我遇到了关于 dispatch 未定义的相同错误模式,然后不是函数。我错过了什么?
addUploadToDocument(...).then is not a function
Uncaught TypeError: Cannot read property 'then' of undefined
我可以确认以下内容: - Redux-thunk 设置正确。它在我们的生产版本中工作并启动。 - 正在从我的组件调用该操作。只是不确定是否派送。我可以成功上传图片,但在操作解决之前发起了回调。
这是我的操作代码:
// actions.js
// thunk
export function loadImage(document, file) {
return (dispatch, getState) => {
return dispatch(addUploadToDocument(document, file))
.then(() => {
console.log('Thunk is loaded.. chyeah.');
var uploads = this.props.uploads
var image = uploads[uploads.length - 1]
ReactSummernote.insertImage(image.previewURL, $image => {
$image.css("width", Math.floor($image.width() / 2));
$image.attr("alt", image.name);
});
});
}
}
//image processing action
export function addUploadToDocument(document, file) {
return (dispatch, getState) => {
//const position = getState().bodyEditorSelection.index
const base64Reader = new FileReader()
base64Reader.addEventListener('load', function() {
const base64 = base64Reader.result.replace(/data:.*?base64,/, '')
const key = Math.random().toString(36).substring(7)
const destination_path = `/uploads/${document.name}/${key}-${file.name}`
return dispatch({
type: DOCUMENT_ADD_UPLOAD,
payload: {
path: destination_path,
type: file.type,
base64: base64,
name: document.name,
previewURL: window.URL.createObjectURL(file),
//position: position
}
})
})
base64Reader.readAsDataURL(file)
}
}
这是我的组件。
handleImageUpload (files, editor, welEditable) {
var file = files[files.length -1];
this.props.loadImage(this.props.document, file)
}
render() {
this.syncBodyEditorState()
this.state = this.state || {}
return (
<ReactSummernote
value={this.props.body}
options={{
height: 750,
dialogsInBody: true,
toolbar: [
["style", ["style"]],
["font", ["bold", "underline", "clear"]],
["fontname", ["fontname"]],
["para", ["ul", "ol", "paragraph"]],
["table", ["table"]],
["insert", ["link", "picture", "video"]],
["view", ["codeview"]]
]
}}
onImageUpload={this.handleImageUpload}
onChange={this.handleChange}
/>
)
}
}
function mapStateToProperties(state) {
const currentDocument = currentDocumentSelector(state).currentDocument
return {
document: currentDocument,
bodyEditorSelection: state.bodyEditorSelection,
body: currentDocument.content.body,
uploads: currentDocument.content.uploads
}
}
export default connect(mapStateToProperties, {
SummernoteEditor,
updateDocumentBody,
updateBodyEditorSelection,
addUploadToDocument,
loadImage
})(SummernoteEditor)
我是不是遗漏了一些微不足道的东西?我看了几十个例子,砰的一声把我难住了!
在此先感谢您的帮助。
现在你的 addUploadToDocument
函数没有 return 承诺,尽管如此你 .then
你的 dispatch
方法(而且它只是一个 thunk returns 一个普通对象)。如果你需要继续,你可以将 addUploadToDocument
函数的内容包装在一个 promise 中,然后它就可以了。这里有一些不同的方法,通过一些折射来帮助您入门(假设 'load' 事件只能发生一次):
export function loadImage(document, file) {
return (dispatch, getState) => {
const base64Reader = new FileReader();
const promise = new Promise((resolve, reject)=> {
base64Reader.addEventListener('load', resolve)
})
.then(()=> {
const base64 = base64Reader.result.replace(/data:.*?base64,/, '')
const key = Math.random().toString(36).substring(7)
const destination_path = `/uploads/${document.name}/${key}-${file.name}`
dispatch({
type: DOCUMENT_ADD_UPLOAD,
payload: {
path: destination_path,
type: file.type,
base64: base64,
name: document.name,
previewURL: window.URL.createObjectURL(file),
//position: position
}
})
})
.then(()=> {
console.log('Thunk is loaded.. chyeah.');
var uploads = this.props.uploads
var image = uploads[uploads.length - 1]
ReactSummernote.insertImage(image.previewURL, $image => {
$image.css("width", Math.floor($image.width() / 2));
$image.attr("alt", image.name);
});
})
base64Reader.readAsDataURL(file);
return promise;
}
}