React Image Upload组件的图像预览null错误

时间:2019-08-19 05:52:53

标签: javascript reactjs redux image-upload

反应ImageUploadContainer组件绑定数据可以正常工作,但是会收到javascript错误“未捕获的TypeError:无法读取null的属性'imagePreviewUrl'”

该操作似乎工作正常,并且可以很好地提取图像数据,但我不知道为什么会发生此错误。

它是由redux和react构建的。

ImageUploadConatiner.js(儿童)

import React, {Component} from 'react'
import {bindActionCreators} from 'redux'
import { FormattedMessage } from 'react-intl'
import {getFile} from '../../../selectors/qna'
import {connect} from 'react-redux'
import classnames from 'classnames'
import { getLocale } from '../../../selectors/session'
import actions from '../../../actions/qna/form'
import FormGroup from 'react-bootstrap/lib/FormGroup'
import ControlLabel from 'react-bootstrap/lib/ControlLabel'

export const mapStateToProps = (state) => {
  const file = getFile(state);
  let isMobile = true;
  if(typeof window !== 'undefined' && window.innerWidth >= 992)
    isMobile = false;

  return {
    file,
    isMobile,
    imageUrl: undefined,
    locale: getLocale(state)
  }
};

const mapDispatchToProps = dispatch => {
  return {
    actions: bindActionCreators({
      ...actions
    }, dispatch)
  }
};

export const mergeProps = (mappedProps,dispatchProps) => {
  return Object.assign(mappedProps,{
    actions: {
      imageUpdate: (idx,file,imagePreviewUrl) => {
        dispatchProps.actions.qnaFormFileUpdate({ idx, file, imagePreviewUrl })
      },
      imageDelete: (idx) => {
        dispatchProps.actions.qnaFormFileDelete({ idx: idx.num })
      }
    }
  })
}

@connect(mapStateToProps, mapDispatchToProps,mergeProps)
export default class ImageUpload extends Component {

  constructor(props){
    super(props);
    this.state = {
    };
    this._handleImageChange = this._handleImageChange.bind(this)
  }

  _handleImageChange(e) {
    e.preventDefault()
    const { actions, file } = this.props;
    const fileCount = Object.keys(file).length;

    let reader = new FileReader();
    let imageFile = e.target.files[0];

    reader.onloadend = (upload) => {
      actions.imageUpdate(fileCount, imageFile, reader.result)
    };

    if (imageFile)
      reader.readAsDataURL(imageFile);

    this.input.value = null
  }

  componentDidMount() {
    const { actions, imageUrl } = this.props;
    if(imageUrl !== undefined && imageUrl) {
      actions.imageUpdate({ file: null, imagePreviewUrl: imageUrl })
    }
  }

  render() {

    const { actions, file, locale } = this.props;

    let $imagePreview = [];
    const fileCount = Object.keys(file).length;

    if (file !== undefined) {
      for (let num in file) {
        if (file[num].imagePreviewUrl != null) {
        $imagePreview[num] = (
          <div className='qna-file-input-delete-container' key={`qnaPreview-${num}`}>
            <div className='qna-file-input-delete-btn'>
              <button className='qna-file-delete-btn'
                      onClick={(e) => {
                        e.preventDefault();
                        actions.imageDelete({num})
                      }}>
                <i className={ classnames('fa fa-times-circle-o', {'fa-1x': this.props.isMobile}, {'fa-2x': !this.props.isMobile}) }/>
              </button>
            </div>
            <img src={file[num].imagePreviewUrl}/>
          </div>
        );
        }
      }
    }
    return (
      <div>
        <FormGroup controlId="formHorizontalType">
          <ControlLabel><FormattedMessage id={`${locale}.user.qna.attachImage`}/></ControlLabel>
          { fileCount < 10 ?
            <button className="button button-outline button-sm" style={{width: '160px', marginBottom: '16px', display: 'block'}}
                    onClick={(e) => {
                      e.preventDefault();
                      if (this.input) {
                        this.input.click();
                      }
                    }}>
              <FormattedMessage id={`${locale}.user.qna.selectImage`}/>
            </button>
            : undefined
          }
          <div style={{color:'#ff4949'}}><FormattedMessage id={`${locale}.user.qna.limitMessage`}/></div>
          <div className="qna-file-input-controls">
            <input style={{display: 'none'}} type="file"
                   ref={(ref) => {
                     this.input = ref
                   }}
                   accept='.gif, .jpg, .png, .jpeg, .bmp'
                   onChange={this._handleImageChange}/>
            {$imagePreview}
          </div>
        </FormGroup>
      </div>
    )
  }

}

QnaContainer.js(父母)

import React, {Component} from "react";
import _, {union} from 'lodash'
import {FormattedMessage, FormattedHTMLMessage, FormattedDate, FormattedTime, injectIntl} from 'react-intl'
import ProgressBar from "../../../components/ProgressBar";
import Select from "../../../components/select/Select";
import HelmetContainer from './HelmetContainer';
import ListSectionContainer from '../../../containers/faq/ListSectionContainer'
import ImageUpload from "./ImageUploadContainer";
import {getLocale} from "../../../selectors/session";
import {getQnAForm, getQnAFormPayment} from "../../../selectors/qna";
import {getOrderByOrderNo, getOrderNos} from "../../../selectors/user/order/index";
import {getFAQ} from "../../../selectors/about";
import {getLock} from "../../../selectors/share";
import {bindActionCreators} from "redux";
import actions from "../../../actions/qna/form";
import uiActions from "../../../actions/ui";
import shareActions from "../../../actions/share";
import {asyncConnect} from "redux-connect";
import {startUp as qnaFormStartUp} from "../../../sagas/qna/form";
import moment from "moment-timezone";
import {ICONS} from "../../../constants/Icons";
import Icon from "../../../components/Icon";
import Dialog from "../../../components/dialog/Dialog";
import { Link } from 'react-router'

export const mapStateToProps = state => {
  const locale = getLocale(state)
  const QnAForm = getQnAForm(state)
  const faq = getFAQ(state)
  const orderNos = getOrderNos(state)
  const isLockSubmit = getLock(state, 'QnA', 'submit')

  (...)

  return {
    faq,
    locale,
    day,
    koreaTime,
    holidays,
    isOpen,
    orderList,
    formState: QnAForm.formState,
    typeValue: QnAForm.type,
    paymentValue: QnAForm.payment,
    subjectValue: QnAForm.subject,
    contentValue: QnAForm.content,
    isFetching: QnAForm.isFetching,
    isPayment: getQnAFormPayment(state),
    isConfirm: state.share.confirm,
    links: {
      primary: '/faq'
    }
  }
}

const mapDispatchToProps = dispatch => {
  return {
    actions: bindActionCreators({
      ...actions, ...uiActions, ...shareActions
    }, dispatch)
  }
}

export const mergeProps = (mappedProps, dispatchProps) => {
  return Object.assign(mappedProps, {
    actions: {
      typeChange: (e) => {
        dispatchProps.actions.qnaTypeSelect(e)
      },
      listChange: (e) => {
        dispatchProps.actions.qnaPaymentSelect(e)
      },
      subjectTextUpdate: (e) => {
        dispatchProps.actions.qnaSubjectTextUpdate(e)
      },
      contentTextUpdate: (e) => {
        dispatchProps.actions.qnaContentTextUpdate(e)
      },
      submit: () => {
        if (!mappedProps.isLockSubmit) {
          dispatchProps.actions.generalBtnLock('QnA', 'submit')
          dispatchProps.actions.qnaSubmitRequest()
        }
      }
    }
  })
}

@asyncConnect([{
  promise: ({store: {runSaga}, helpers: {client}}) => {
    const task = runSaga(qnaFormStartUp, client)
    return task.done
  }
}], mapStateToProps, mapDispatchToProps, mergeProps)
@injectIntl
export default class QnaContainer extends Component {

  constructor(props) {
    super(props)
    this.state = {
      alert: false,
      categoryValue: '',
    }
  }

  render() {
    const { locale, actions, faq, links: {primary}, intl} = this.props;

    return (

     (...)

      <div className="field">
         <ImageUpload />
      </div>

     (...)

    );
  }
}

0 个答案:

没有答案