简体   繁体   中英

Proper way to use Action in Redux

I am working a color guessing game. I have an action called generateColors() that generate 9 colors and an answer will be randomly chosen from those 9 colors. My App.js renders Header.js and BoxGrid.js .

Currently I call generateColors() in BoxGrid.js . What is the right way to pass answer to Header.js ? Should I call generateColors() in App.js instead?

BoxGrid.js

import React, {Component} from 'react';
import {connect} from 'react-redux';

import Box from '../components/box';
import { generateColors } from '../actions';

class BoxGrid extends Component{

    componentDidMount(){
        this.props.generateColors();
    }

    render(){
        return(
            <div>
                <div className="grid">
                    {this.props.colors.map((color)=>{
                        return <Box key={color} color={color}/>
                    })}
                </div>
            </div>
        )
    }
}

function mapState({colors}){
    return {colors};
}

export default connect(mapState,{generateColors})(BoxGrid);

Thanks in advance.

I'm not sure how the application looks like so I may be wrong.

Because you're using Redux, just save the answer to your Redux store, and connect Header to the store (or just connect App and pass the props down to Header , both are fine)

Personally I'd prefer to put that action in App.js in this case, so the BoxGrid doesn't need do care about any application logic, just renders the UI. But I think this is just personal tastes and there is no correct answer.

You can see the faq of Redux doc here:

Should I only connect my top component, or can I connect multiple components in my tree?

http://redux.js.org/docs/faq/ReactRedux.html#should-i-only-connect-my-top-component-or-can-i-connect-multiple-components-in-my-tree

I assume by answer you mean that the user is picking a color, and you want to pass that user input from one component to another. There are a couple of ways to do this. You could pass down a function from App as a prop to the component below, and when that function is called, it sets local state within App , which is also passed down to child components:

class App extends Component {
  constructor(props) {
     super(props)
     this.state = {
        answer: null
     }
  }

  updateAnswer(answer) {
     this.setState({ answer: answer })
  }

  render () {
     return <div>
        <Header answer={this.state.answer} />
        <BoxGrid answer={this.state.answer} updateAnswer={this.updateAnswer.bind(this)} />
     </div>
  }
}

Then, when BoxGrid calls this.props.updateAnswer(answer) it will get passed to header. This doesn't use the Redux store.

The other way is to use the Redux store, and call an action. If you are sharing data between several components this probably makes more sense than using local state as above. Very similar to what you have already posted, you can just connect any component and grab the global state. Instead of setting local state in the App component, you would have an answer reducer, which would look like:

function answer (state = { answer: null }, action) {
  if (action.type === 'saveAnswer') {
    return { answer: action.answer }
  }
}

And a saveAnswer action creator like:

function saveAnswer (answer) {
  return {
     type: 'saveAnswer',
     answer: answer
  }
}

Then if you connect you App component with mapStateToProps , function you just grab the answer out of the store and return it as props, which can be passed down to any child component. As your hierarchy gets more complex, you can choose to connect any child component, but if you just have 3 total components, it probably makes more sense to just connect App and pass down data from the store as props.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM