connect()不调度操作[React-Redux]

时间:2019-12-22 10:15:09

标签: reactjs react-native redux react-redux

更新:12/23/2019

我更新了Screen.js,使其同时包含@Will Jenkins和@HuỳnhTuân的建议,但仍然无法正常工作。

此外,我添加了两行调试代码,以期使问题更加清楚。


我是React的新手,也是Redux的新手-并尝试通过遵循basic tutorial(这对我来说比基本的东西先进)来学习如何使用Redux来控制我的应用程序状态。我还查看了redux上的this tutorialthis tutorial,以及关于SO的类似帖子,但到目前为止都无济于事。

我的项目2个组件;一个文本组件以显示从外部API获得的消息,以及一个按钮,在点击该按钮时,该按钮会从API获取数据并重新呈现该消息。而已!

但是,当我点击按钮时,尽管尽可能严格地遵循了本教程,但是什么也没有发生。我确实将根容器包装在<Provider>中,并connect()将我的演示组件添加到store中。但是不知何故它仍然无法正常工作。

很显然,这里不正确。有人可以向我指出我做错了什么吗?下面是我的代码(为简洁起见,省略了导入)。

App.js

export default function App() {
    return (
        <Provider store={store}>
            <Screen />
        </Provider>
    )
}

Screen.js

class Screen extends React.Component {

    constructor(props) {
        super(props)
        //this.state = {question: ''}
        this.state = {reducer: { question } }
    }

    getDataFromAPI() {
        fetch('https://opentdb.com/api.php?amount=5&type=boolean')
        .then((response) => response.json())
        .then((responseJson) => {
            console.log("before", this.props.question) // undefined
          this.props.updateQuestion(responseJson.results[0].question)
            console.log("after", this.props.question) // undefined
        })
        .catch((error) => {
            console.error(error);
        });
    }

    render() {
        return (
            <View style={{flex: 1, backgroundColor:'fff', alignItems:'center', justifyContent:'center'}}>
                <Text> {this.props.question} </Text>
                <Button title='New Trivia' onPress={() => this.getDataFromAPI()} />
            </View>
        );
    }

}

{/*const mapStateToProps = (state) => {
    return {
        question: state.question
    }
}*/}
const mapStateToProps = ({ reducer: { question } }) => {
    question
}

const mapDispatchToProps = dispatch => ({
    updateQuestion: (question) => dispatch(updateQuestion(question))
})

export default connect(mapStateToProps, mapDispatchToProps)(Screen)

Actions.js

export const updateQuestion = (response) => ({
    type: UPDATE_QUESTION,
    question: response,
})

ActionTypes.js

export const UPDATE_QUESTION = "UPDATE_QUESTION"

store.js

export default createStore(rootReducer)

index.js

export default combineReducers({reducer})

Reducer.js

const initialState = { question: '' }

export default function (state = initialState, action) {
    switch(action.type) {
        case UPDATE_QUESTION: {
            return {...state, question: action.question}
        }
        default: {
            return state
        }
    }
}

2 个答案:

答案 0 :(得分:1)

威尔·詹金斯(Will Jenkins)的修正非常棒,但他从mapStateToProps返回时,错过了用括号将对象包装起来的想法。由于未返回任何内容,因此返回undefined。显式编写ps或将mapState定义为

return { question }

顺便说一句,不要太卑鄙或其他,请尝试自己解决此类错误。在我们的代码中经常犯错误,这是学习的最佳机会。我建议您尝试自己解决某些错误(例如某些返回未定义的结果,或者不是您期望的结果,或者您调用的函数未达到应有的功能),因为那样您就可以学习如何解决问题,并成为JS程序员更扎实。

答案 1 :(得分:0)

您需要导入要调用的Action,然后分派它以在组件中调用Action Redux。 将您的 Screen.js 更改为:

import { updateQuestion } from './Actions'
class Screen extends React.Component {

  constructor(props) {
      super(props)
      this.state = {question: ''}
  }

  getDataFromAPI() {
      const { updateQuestion } = this.props;
      fetch('https://opentdb.com/api.php?amount=5&type=boolean')
      .then((response) => response.json())
      .then((responseJson) => {
        updateQuestion(responseJson.results[0].question)
      })
      .catch((error) => {
          console.error(error);
      });
  }

  render() {
      return (
          <View style={{flex: 1, backgroundColor:'fff', alignItems:'center', justifyContent:'center'}}>
              <Text> {this.props.question} </Text>
              <Button title='New Trivia' onPress={() => this.getDataFromAPI()} />
          </View>
      );
  }

}

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

const mapDispatchToProps = dispatch => ({
  updateQuestion: (question) => dispatch(updateQuestion(question)) 
})
export default connect(mapStateToProps, mapDispatchToProps)(Screen)