Redux-React:调度函数返回的值未传递给子组件

时间:2017-07-01 02:25:39

标签: reactjs redux redux-thunk

我实际上是反应 - 还原的新手,所以我只需要一些帮助,试图理解我在这里犯的任何语法或逻辑错误......

基本上,我想显示从其他服务器获取的报告。函数'fetchNames'处理它,函数'fetchdownloadable'创建一个返回链接,允许通过身份验证并以pdf onClick下载报告。

所以我在控制台上调试了,我相信代码的执行顺序有问题...当我调试时...我注意到: 首先执行fetchnames以获取json数组中的所有报告数据... 然后为reports数组中的每个对象调用fetchDownloadable,并在SampleChild上返回'undefined'值... 然后使用未定义的值执行SampleChild ... 然后我们回来执行fetchDownloadable函数,该函数在控制台上打印链接值,并在reducer上调度操作,在reducer中返回'state'而不是'action.reports_uri'...

提前致谢!

SampleParent.js

12

SampleChild.js

import React, {Component} from 'react'
import { connect } from 'react-redux'
import { fetchNames, fetchDownloadable } from '../../actions/actions'
import SampleChild from '../ui/SampleChild'
class SampleParent extends Component {
constructor(props) {
    super(props);
    this.fetchDownloadLink = this.fetchDownloadLink.bind(this)
}
componentDidMount() {
    const { dispatch } = this.props
    dispatch(fetchNames())
}
fetchDownloadLink(uri){
    this.props.dispatch(fetchDownloadable(uri))
}
render() {
    return (<div><ul id="myUL">
                {this.props.reports.map((report) => (
                    <li><SampleChild
                            key={report.id}
                            label={report.label}
                            uri={this.fetchDownloadLink("http://localhost:8080/sample"+report.uri+".pdf")}
                        /></li>))}
            </ul></div>
    )}
}
function mapStateToProps(state) {
const { reports } = state
return {
    reports
}}
export default connect(mapStateToProps)(SampleParent)

Action.js

import React, { Component } from 'react'
export default class SampleChild extends Component {
render() {
    const { key, label, uri } = this.props
    return (
    <div className="inside_SampleChild" id={label}>
        {label}
        <a href={uri}><img src="../images/pdf-file_128.png" height="25px" width="25px"></img></a>
    </div>
    )}}

Reducers.js

import C from '../constants'
import fetch from 'isomorphic-fetch'  

export const fetchNames = value => dispatch => {
var obj = { method: 'GET', headers: { 'Authorization': 'Basic ***', 'Accept': 'application/json' },
    'credentials': 'include'};
fetch('http://localhost:8080/samplelink', obj)
    .then(response => {
        if (response.status !== 200) {
            throw Error(response.status);
        }return response;})
    .then((response) => response.json())
    .then(resourceLookup => {
        var arr = [];
        var length = resourceLookup.resourceLookup.length;
        for(var i = 0 ; i< length ; i++){
            arr.push(resourceLookup.resourceLookup[i]);}
        dispatch({
            type: C.FETCH_LIST_REPORTS,
            reports: arr})}).
catch(error => {
    console.log("There was this  error" + error);});}

export const fetchReportDownloadable = (uri) => dispatch => {
var obj = {
    method: 'GET',
    headers: {
        'Authorization': 'Basic ***=',
        'Accept': 'application/json'
    },
    'credentials': 'include'
};
fetch(uri, obj)
    .then(response => {
        if (response.status !== 200) {
            throw Error(response.status);
        }
        return response ;
    })
    .then((response) => response)
    .then(resourceLookup => {
        console.log(`resourceLookup URL: ${resourceLookup.url}`)
        dispatch({
            type: C.FETCH_DOWNLOADABLE,
            report_uri: resourceLookup.url
        })
    }).
catch(error => {
    console.log("There was this  error" + error);
});}

1 个答案:

答案 0 :(得分:1)

我会尝试解释发生的事情。

首先,您遇到的第一个问题是您传递的错误值或uri的未定义值:

<li>
  <SampleChild key={report.id} label={report.label}
     uri={this.fetchDownloadLink("http://localhost:8080/sample"+report.uri+".pdf")}
                        />
</li>

这里uri是一个函数,它在第一个渲染时触发,它调度fetchDownloadable(uri)动作,但它不会返回任何值。因此uri未定义。

其次,您的减速器中使用C.FETCH_REPORT_DOWNLOADABLE常量。但是,您从不调度该类型的操作,操作将调度C.FETCHING_DOWNLOADABLE。因此减速器没有做任何事情,所以状态不会改变。我的第二条评论是C.FETCH_LIST_REPORTS,这对你来说无关紧要,所以我错了。

我要做的是从服务器端创建下载链接。使用报告对象将其发回。这样,您就不需要发送两个操作来列出您的报告。然后,我将在componentWillMount()中发送我的操作,一旦完成获取数据,状态将会更改 - 如果您再次发送了正确的操作 - 并且您将使用在同一个对象中下载URL。

<强>更新

好的,我想我现在明白了。我要做的是将uri作为字符串发送到SampleChild,然后当它安装时,我将触发fetchDownloadable函数。

<强> SampleParent

import React, {Component} from 'react'
import { connect } from 'react-redux'
import { fetchNames, fetchReportDownloadable } from '../../actions/actions'
import SampleChild from '../ui/SampleChild'
class SampleParent extends Component {
constructor(props) {
    super(props);
    this.fetchDownloadLink = this.fetchDownloadLink.bind(this)
}
componentDidMount() {
    const { dispatch } = this.props
    dispatch(fetchNames())
}
fetchDownloadLink(uri){
    this.props.dispatch(fetchReportDownloadable(uri))
}
render() {
    return (<div><ul id="myUL">
                {this.props.reports.map((report) => (
                    <li><SampleChild
                            key={report.id}
                            label={report.label}
                 uri={"http://localhost:8080/sample"+report.uri+".pdf"}
                 download={this.fetchDownloadLink}
                    /></li>))}
            </ul></div>
    )}
}
function mapStateToProps(state) {
const { reports } = state
return {
    reports
}}
export default connect(mapStateToProps)(SampleParent)

<强> SampleChild

import React, { Component } from 'react'
export default class SampleChild extends Component {
componentDidMount() {
    this.props.download(this.props.uri);
}
render() {
    const { key, label, uri } = this.props
    return (
    <div className="inside_SampleChild" id={label}>
        {label}
        <a href={uri}><img src="../images/pdf-file_128.png" height="25px" width="25px"></img></a>
    </div>
    )}}

现在应该发生的是,您将首先在SampleParent中获取报告,然后将信息传递给SampleChild。每当安装SampleChild时,它都会触发fetchDownloadable操作,该操作会在返回时下载发送给它的uri