【问题标题】:How to handle action in Reducer?如何处理 Reducer 中的动作?
【发布时间】:2018-02-03 23:42:22
【问题描述】:

如何定位减速器中数组中的哪个元素/对象,我必须将动作传递给?我试图弄清楚我对减速器采取了什么行动。或者我如何更改影响对象中的number 值。所以我在一个带有 TouchableOpacity 的视图中渲染数组,它 onPress 我调用动作调度如下:

import React, { Component } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';

class NewData extends Component {
    render(){
    const renData = this.props.newData.map((data, idx) => {
        return (
            <View key={idx}>
              <TouchableOpacity
                onPress={() => this.props.incNum(data.id)}
                //not sure how to toggel dispatch call above, for onPress
              >
              <Text style={styles.welcome}>{data.id} - {data.name} - {data.number}</Text>
              </TouchableOpacity>
            </View> 
        )
    });

        return(
            <View>
          {renData}
      </View>   
        );
    }
}


function mapStateToProps (state) {
  return {
    newData: state.newData
  };
};


//I think I need to create a toggle here:
//Something like: this.props.newData.id ? incNum : decNum


function mapDispatchToProps (dispatch) {
  return {
    incNum: (id) => {
      dispatch({
        type: "INC_NUM",
        payload: id
      })
    },
     decNum: (id) => {
      dispatch({
        type: "DEC_NUM",
        payload: id
      })
    }
  };
};  

export default connect( mapStateToProps, mapDispatchToProps )( NewData )

我的减速机:

const initialState = [
      {
        id: '01',
        name: 'Name One',
        number: 11
      },
      {
        id: '02',
        name: 'Name Two',
        number: 22
      },
      {
        id: '03',
        name: 'Name Three',
        number: 33
      }

    ]

export default function newData (state = initialState, action) {
  switch (action.type) {
    case "INC_NUM":
      return {
        ...state,
        number: this.state.number ++ // <== need help here.
      }
    case "DEC_NUM":
      return {
        ...state,
        number: this.state.number --
      }
    default:
      return state
  }
}

我认为&lt;TouchableOpacity onPress={() =&gt; this.props.incNum(data.id)} 将绑定要更改的id。传递payload: id 会将id 传递给reducer。但是如何更新减速器中的值?我现在可以不用切换开关。我想了解如何在减速器中传递值并相应地更新。

谢谢。


EDIT1:

所以我现在的减速器是:

const initialState = {
  1: {
     id: '01',
     name: 'Name One',
     number: 11
    },
  2: {
     id: '02',
     name: 'Name Two',
     number: 22
    }
}


export default function newData (state = initialState, action) {
  switch (action.type) {
    case "INC_NUM":
      return {
        ...state,
        [action.payload]: {
          ...state[action.payload], 
          number: state[action.payload].number++  <== Line 58 in ERROR screenshot
        }
    case "DEC_NUM":
        return {
        ...state,
        [action.payload]: {
          ...state[action.payload], 
          number: state[action.payload].number--
        }
    default:
      return state
  }
}

我渲染它的方式是:

class NewData extends Component {
  render(){

    const renData = Object.keys(this.props.newData).map((key, idx) => {
      let data = this.props.newData[key]
        return (
        <View key={idx}>
          <TouchableOpacity

            onPress={() => this.props.updateNum(data.id)}
          >
          <Text style={styles.welcome}>{data.id} - {data.name} - {data.number}</Text>
          </TouchableOpacity>
        </View> 
       )
    });

    return(
        <View>
            {renData}
        </View>   
    )
  }
}


function mapDispatchToProps (dispatch) {
  return {
    updateNum: (id) => {
      INC_NUM({
        type: "INC_NUM",
        payload: id
      })
    }
  };
};

reducer 中的所有内容都按预期显示。但是当我单击并调用该操作时,出现错误:

【问题讨论】:

  • 你需要在你的 reducer 中做一些过滤。您当前的 reducer 正在尝试更新不存在的 state.number。此外,您的 initialState 应该是一个对象而不是数组。我通常像这样按 id 映射我的状态: { 1: {id: 1, name: 'number one'...}, 2: {id:2,... }, .... }
  • 谢谢。请您指出一些我可以阅读/参考的内容。我是 React 和 Redux 的新手,正在努力学习。
  • 另外,您应该使用您的 action.payload 过滤您的状态对象。这就是您的“身份”的来源。希望这会有所帮助。
  • 大约一年前我不得不同时学习这两种方法。在尝试结合学习两者之前,我强烈建议在几个教程中分别学习 React 和 Redux。 redux.js.org/docs/basics/ExampleTodoList.html 是 redux 的一个很好的开始。如有任何问题,请随时 PM 我。另一个资源:egghead.io/courses/getting-started-with-redux
  • 谢谢 .. 自过去 2 个月以来,我已经多次阅读提到的两个教程。我想我的问题更多是与 JS 相关的,我无法弄清楚。

标签: reactjs react-native redux react-redux


【解决方案1】:

你的减速器似乎比它需要的复杂得多,下面是更简单的方法,希望这会有所帮助。

const initialState = {
  1: {
     id: '01',
     name: 'Name One',
     number: 11
    },
  2: {
     id: '02',
     name: 'Name Two',
     number: 22
    }
}


    export default function newData (state = initialState, action) {
      switch (action.type) {
        case "INC_NUM":
             const newState = {...state};
             newState[action.payload].nubmer++;
             return newState;

        case "DEC_NUM":
            const newState = {...state};
            newState[action.payload].nubmer--;
            return newState;

        default:
          return state
      }
    }

【讨论】:

  • 谢谢。试过你的代码。没有错误。但我没有看到{data.number} 有任何变化。它保持不变。这不应该改变吗?
  • 对不起。我将减速器中的id 更改为与它指向的相同。就像 1 一样,我将 id:01 更改为 id:1 并且它起作用了。谢谢。
【解决方案2】:

您的问题似乎出在您的 reducer 和您的状态结构中。您没有使用 ID 来识别要更新的 keyval 对。

首先,我将您的 initialState 修改为一个对象并使用 id 作为您的键:

const initialState = {
  1: {name: 'Name One', number: 11},
  2: {name: 'Name Two', number: 22},
  3: {name: 'Name Three', number: 33}
}

然后在你的减速器中:

case "INC_NUM":
  return {
    ...state,
    [action.id]: {
      ...state[action.id], 
      number: state[action.id].number++
    }
  }

我知道语法很复杂,但扩展运算符是一个很好的简写,否则会更难阅读。

【讨论】:

  • 试过这个并正确渲染了对象。现在,当我单击某个项目并调用 action 时出现错误。编辑了我的问题EDIT1。我错过了什么/做错了什么?另外,我渲染renData 正确吗?
  • 嗨。我将如何将更多数据附加到此状态?我正在调用 API 以向状态添加更多数据,但不知道如何使用对象执行此操作。使用数组很容易 (...state, ...data) 请告诉我如何使用 Objects 做同样的事情。
  • 在上面的示例中,只需将state[action.id].number++ 替换为一些新数据(例如 action.newpayload),然后您将附加该数据。从技术上讲,您在此处的示例中附加了 number++。
猜你喜欢
  • 2017-06-09
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 2015-12-24
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多