在react-redux组件

时间:2016-12-02 08:23:52

标签: javascript reactjs redux

我正在尝试在组件中进行初始提取并在获取数据时渲染Loader。但是在isFetching变为true之前的render()调用因此我的组件闪烁(isFetching = false => isFetching = true => isFetching = false)。 我知道我可以在没有数据的情况下渲染Loader并且眨眼就会消失,但也许有人知道更优雅的解决方案?

操作/ files.js

import 'whatwg-fetch';

import { REQUEST_FILES, RECEIVE_FILES } from '../constants'

export function requestFiles() {
  return { type: REQUEST_FILES };
}

export function receiveFiles(files) {
  const payload = files;
  return { payload:payload, type: RECEIVE_FILES };
}

export function getFile(hash) {
  return dispatch => {
    dispatch(requestFiles());
    fetch('/api/files/'+hash+'/info', {
        method: 'GET',
      })
      .then(response => response.json())
      .then(data => {
        if (data.error) {
        }
        else {
          dispatch(receiveFiles([data]));
        }
      })
      .catch(error => { console.log('request failed', error); });
  }
}

减速器/ files.js

import { REQUEST_FILES, RECEIVE_FILES } from '../constants'

var initialState = {
    items: [],
    isFetching: false
}

const files = (state = initialState, action) => {
  switch (action.type) {
    case RECEIVE_FILES: {
      return { ...state, isFetching:false, items: action.payload };
    }
    case REQUEST_FILES: {
      return { ...state, isFetching:true };
    }
    default:
      return state;
  }
}

export default files;

组件/智能/ fileboard.jsx

require('styles/app.scss');

import React from 'react';
import { Link } from 'react-router'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

import * as filesActions from '../../actions/files'

import Loader from '../dumb/loader'
import withBoard from './board'
import DumbFileboard from '../dumb/fileboard'


let getFileSrc = require('config').default.getFileSrc;

const mapStateToProps = (state) => {
  return {
    files: state.files
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    filesActions: bindActionCreators(filesActions, dispatch)
  }
}


class Fileboard extends React.Component {

  componentWillMount() {
    if (this.props.files.items.length === 0) {
      this.props.filesActions.getFile(this.props.params.hash);
    }
  }

  constructor(props) {
    super(props);
  }

  render() {
    return this.props.files.isFetching ? Loader : (
      <DumbFileboard fileSrc={ getFileSrc(this.props.files.items[0]) } />
    );
  }
}


export default connect(mapStateToProps, mapDispatchToProps)(withBoard(Fileboard));

3 个答案:

答案 0 :(得分:0)

为什么不让初始状态将 isFetching 设置为 true ?使用 createStore 函数创建商店时,可以传递初始状态。

此外,React文档建议在 componentDidMount 中提取数据:

如果您需要从远程端点加载数据,这是实例化网络请求的好地方。在此方法中设置状态将触发重新渲染。

https://facebook.github.io/react/docs/react-component.html#componentdidmount

答案 1 :(得分:0)

在我看来足够优雅,只有三件事:

初始状态中没有files属性。

const mapStateToProps = (state) => {
  return {
    files: state.files
  }
}

为什么不使用州的isFetching属性?

const mapStateToProps = (state) => {
  return {
    files: state.files,
    isFetching: state.isFetching
  }
}

然后

  render() {
    const { isFetching } = this.props;

    return (
      isFetching ? 
        Loader 
        : 
        <DumbFileboard fileSrc={ getFileSrc(this.props.files.items[0]) } />
    );
  }

答案 2 :(得分:0)

我认为你的Loader永远不会被呈现(但是你在显示一个空白的孩子,直到数据加载,然后孩子获取数据并呈现更多东西)。

而不是这个,

  render() {
    return this.props.files.isFetching ? Loader : (
      <DumbFileboard fileSrc={ getFileSrc(this.props.files.items[0]) } />
    );
  }

你需要这个:

  render() {
    return this.props.files.isFetching ? <Loader/> : (
      <DumbFileboard fileSrc={ getFileSrc(this.props.files.items[0]) } />
    );
  }

请注意丢失的</>

看到这个小提琴(案例的模拟): https://jsfiddle.net/free_soul/49bdw76z/

以及带有工作Loader的固定版本:https://jsfiddle.net/free_soul/u0v8e0zg/