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

Redux-React: value returned by a dispatch function is not being passed to child component

实际上我是 react-redux 的新手,所以我只需要一些帮助来理解我在这里犯的任何语法或逻辑错误...

基本上,我想显示从另一台服务器获取的报告。函数 'fetchNames' 处理该问题,函数 'fetchdownloadable' 创建一个 returns 一个 link 允许通过身份验证并下载 pdf onClick 报告。

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

提前致谢!

SampleParent.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)

SampleChild.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>
    )}}

Action.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);
});}

Reducers.js

import C from '../constants'
import { combineReducers } from 'redux'
export const links = (state=null, action) =>
(action.type === C.FETCH_DOWNLOADABLE) ?
    action.report_uri :
    state
export const reports = (state=[], action) => {
switch(action.type) {
    case C.FETCH_LIST_REPORTS :
        return action.reports
    default :
        return state
}}
const rootReducer = combineReducers({
reports,
links
})
export default rootReducer

我会试着解释发生了什么。

首先,您遇到的第一个问题是您传递了错误的值,或者 uri in:

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

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

其次,您在减速器中使用了 C.FETCH_REPORT_DOWNLOADABLE 常量。但是,您永远不会调度该类型的操作,该操作会调度 C.FETCHING_DOWNLOADABLE。因此,reducer 并没有真正做任何事情,所以状态不会改变。我的第二条评论是关于 C.FETCH_LIST_REPORTS,现在与您无关,所以我错了。

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

更新

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

样本父

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 操作,在 return 秒内下载发送给它的 uri