Невозможно выполнить повторную визуализацию страницы после обновления избыточного состояния - PullRequest
0 голосов
/ 08 марта 2019

Здесь я получаю список файлов с диска Google в / dashboard / gdrive. Существует еще одно событие загрузки нового файла. При загрузке состояния избыточности видно, что новый файл хранится в состоянии, но во время повторного рендеринга я не могу получить доступ к состояниям хранилища.

Вот кодовый блок

import React, { Component } from 'react';
import PropTypes from "prop-types";
import {connect} from "react-redux";
import {logoutUser} from "./../../actions/authActions.js";
import {syncCloud} from "./../../actions/cloudActions.js";
import {uploadFile} from "./../../actions/cloudActions.js";

class Gdrive extends Component {
    constructor(){
        super();
        this.state={
            file: null
        }
        this.onChange = this.onChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
        this.handleCancelEvent = this.handleCancelEvent.bind(this);
    }
    onChange(e){
        this.setState({
            file: e.target.files[0]
        });
    }
    onSubmit(e){
        e.preventDefault();
        const data = new FormData();
        data.append('filename', this.state.file);
        this.props.uploadFile(data);
    }
    handleCancelEvent(){
        this.setState({
            file: null
        })
    }
    render() {    
    return (
        <div>
            <table>
                <thead>
                    <tr><th>fileid</th><th>filename</th></tr>
                </thead>
                <tbody>
                    {this.props.cloud.files.data.map(file =>(
                        <tr>
                            <td>{file.id}</td>
                            <td>{file.name}</td>
                        </tr>
                    ))}
                </tbody>
            </table>
            <fieldset>
                <form noValidate onSubmit={this.onSubmit}>
                <div>
                    <label>filename</label>
                    <input type="file" onChange={this.onChange} name= "filename"></input>
                </div>
                <div>
                    <button type="submit">Upload</button> 
                    <button onClick={this.handleCancelEvent}>Cancel</button>
                </div>
                </form>
            </fieldset>
        </div>
    )
  }
}
Gdrive.propTypes = {
    logoutUser: PropTypes.func.isRequired,
    auth: PropTypes.object.isRequired
  };
const mapStateToProps = state => ({
    auth: state.auth,
    cloud: state.cloud
});
export default connect(
    mapStateToProps,
    { logoutUser, syncCloud, uploadFile }
  )(Gdrive);

и вот действие uploadFile

export const uploadFile = (file) => dispatch => {
axios.post('/gdrive/upload', file)
.then(rslt => {
    dispatch({
        type: UPLOAD_FILE,
        payload: {id: rslt.data.fileid, name: rslt.data.filename}
    })
})
.catch(err => {
    dispatch({
        type: GET_ERRORS,
        payload: err
    })
});

}

Вот редуктор

import {SYNC_CLOUD, UPLOAD_FILE} from './../actions/types';

const initialState = {
    files: {}
};

export default function(state=initialState, action){
    switch(action.type){
        case SYNC_CLOUD:
            return{
                ...state,
                files: action.payload
            };
        case UPLOAD_FILE: 
            return{
                ...state,
                files: state.files.data.concat(action.payload),
            };
        default: 
            return state;
    }
}

скриншот с ошибкой

Ответы [ 2 ]

0 голосов
/ 08 марта 2019

Я думаю, что ваш редуктор неправильно отображен. Ключ здесь в том, чтобы объявить начальное состояние как пустые файлы, а не как пустой объект. А также объединение существующего массива с ответом от API (полезной нагрузки).

Измените ваш редуктор на что-то вроде этого:

 import {SYNC_CLOUD, UPLOAD_FILE} from './../actions/types';

const initialState = {
    files: []
};

export default function(state=initialState, action){
    switch(action.type){
        case SYNC_CLOUD:
            return{
                ...state,
                files: action.payload
            };
        case UPLOAD_FILE: 
            return{
                [...state, action.payload],
            };
        default: 
            return state;
    }
}

И измените функцию рендеринга на

<tbody>
       {this.props.cloud.files.map(file =>(
            <tr>
                 <td>{file.id}</td>
                  <td>{file.name}</td>
              </tr>
                ))}
 </tbody>
0 голосов
/ 08 марта 2019
Параметр от

mapDispatchToProps до connect должен быть функцией. Либо сделать что-то вроде этого

const mapDispatchToProps= dispatch => bindActionCreators(
    { logoutUser, syncCloud, uploadFile },
    dispatch
)

Или в проходе null в качестве mapDispatchToProps и в своем компоненте используйте создателя действий, как этот this.props.dispatch(uploadFile(data))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...