How to export object.assign and use it's content for validation in another function of same file?

Viewed 262
const INITIAL_STATE = {
  otherStates...,
  phase: " "
};

const mapStateToProps = (state) => {
  return {
    phase: state.phase
  }
}
const mapStateToProps = (state) => {
  return {
    phase: state.phase
  }
}
const mapDispatchToProps = (dispatch) => {
  return {
    onStarting: () => {
      dispatch({type: 'STARTING'})
    }
  }
}
const ConnRootContainer = 
      connect(mapStateToProps, mapDispatchToProps)
      (RootContainer);

I've got a switch statement below and in one case I need to assign phase some text.

export default function (state = INITIAL_STATE, action) {
  switch (action.type) {
    case types.STARTING:
      let phase = " "

      if (state.stateOne < state.StateTwo) {
       count = growth(state, 0)
       phase = "START"
      }

      else if (CONDITION) {        
        phase = "PAUSE"
      }

      else {        
        phase = "STOP"
      }

      coordinates = generate(state.coordinates, variable);
      return {
        ...state,
        coordinates: coordinates,
        phase: phase
              }

    case types.OTHER_TYPE:
      OTHER CASE FILES
      }

    default:
      return state      
  }
}

Phase name has to be used as a condition in another function of same file.

let generate = (data, otherData) => { 
   if({this.props.phase} === "START"){ 
  for (let i = 1; i < otherData; i++) {
    let newX = data[i - 1].x  + FORMULA;
    let newY = data[i - 1].y  + FORMULA;
    data.push({ x: newX, y: newY });
  }
}

if({this.props.phase} === "STOP"){
  while (data.length) {
    data.splice(data.length - 1, 1);
  }
}

return data; 
}

The new error is: this is a reserved word as phase is not passed to the function. How can I improve my code and use state.phase in if statement for validation?

2 Answers

Based on conversation with OP, this code takes place in his reducer, and thus the solution below has been updated to reflect a working solution, allowing OP to update state based on action.type inside his reducer.

Inside your reducer, instead of using Object.assign and then not doing anything with it, you can just put it into the state you return by using destructuring assignment

The key change is following:

let phase = '';

if (otherState1 < otherState2) phase = 'START';

return {
  ...state,
  phase
}

Solution

const { createStore } = Redux;
const { connect, Provider } = ReactRedux;

// Create RootContainer of App
class RootContainer extends React.Component {
  render () {
    return (
      <div>
        <button onClick={this.props.onStarting}>Set Phase to STARTING</button>
        <p>Phase: {this.props.phase}</p>
      </div>
    )
  }
}
// Functions for ReactRedux.connect
const mapStateToProps = (state) => {
  return {
    phase: state.phase
  }
}
const mapDispatchToProps = (dispatch) => {
  return {
    onStarting: () => {
      dispatch({type: 'STARTING'})
    }
  }
}
// Connect React Component to Redux
const ConnRootContainer = 
      connect(mapStateToProps, mapDispatchToProps)
      (RootContainer);

// Setup Initial State
const INITIAL_STATE = {
  otherState1: 1,
  otherState2: 2,
  phase: 'NOT SET'
};

// Define Reducer
function myReducer(state = INITIAL_STATE, action) {
  switch (action.type) {
    case 'STARTING':
      const { otherState1, otherState2 } = state;
      let phase = '';

      if (otherState1 < otherState2) phase = 'START';

      return {
        ...state,
        phase
      }
  }

  return state
}

// Connect reducer to Redux
const store = createStore(myReducer);

// Pass store to ReactRedux.Provider
class App extends React.Component {
  render () {
    return (
      <Provider store={store}>
        <ConnRootContainer />
      </Provider>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.0/react-redux.min.js"></script>
<div id="root"></div>

I'm not entirely sure what Object.assign is accomplishing for you. In your one function you're returning an object, but in the other function you're trying to access a property from state.

I'd suggest you save stage into state, so you can access it from there later. Here's a solution:

Note: In your second function, you're trying to access state.phase, even though you said you wanted to access state.stage

Original Solution

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      otherState1: 1,
      otherState2: 2
    }
    this.getState = this.getState.bind(this);
    this.doSomething = this.doSomething.bind(this);
  }
  
  getState() {
    const { otherState1, otherState2 } = this.state;
    if (otherState1 < otherState2) {
     this.setState({stage : "START"})
    }
  }
  
  doSomething(data, otherData) {
    const { stage } = this.state;
    
     if (stage === "START"){ 
      console.log('phase is START');
    }

    if (stage === "STOP"){
      console.log('phase is STOP');
    }
  }
  
  render() {
    return (
      <div>
        <button onClick={this.getState}>
          Get State
        </button>
        <p>{JSON.stringify(this.state)}</p>
        <button onClick={this.doSomething}>
          Do Something
        </button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Well (given that you can't return it, and it's the same file for both functions) just declare a variable in their common lexical scope:

let object;

function A() {
   object = someValue
}

A()

function B(obj) {
   console.log(obj)
}

B(object)

Of course you should be sure that B() executes after A()

You can always over-engineer this, but currently I don't see any reason to make things more complex.

Related