Получение данных с помощью действия Redux, но не может установить данные в локальное состояние - PullRequest
0 голосов
/ 12 июля 2020

У меня проблемы с доступом к данным, возвращаемым действием Redux в виде одного объекта json. Я могу успешно получить данные и визуализировать их, но только когда я распределяю указанные данные в массив, а затем использую .map () для визуализации содержимого объекта.

Я использую действие для получения данных - Запрос GET возвращает один объект:

export const getHealthData = username => dispatch => {
  dispatch(setHealthDataLoading());
  axios
    .get(`/api/healthData/${username}`)
    .then(res =>
      dispatch({
        type: GET_HEALTHDATA,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

маршрут определяется как:

router.get("/:username", (req, res) => {
  HealthData.find({
    username: req.params.username
  }).then(healthData => res.json(healthData));
});

В моем репозитории я вынужден распространить объект в массив, например, или иначе я не могу получить к нему доступ.

const initialState = {
  healthData: [],
  loading: false,
  sex: "",
  age: "",
  height: "",
  weight: "",
  goal: "",
  activityLevel: ""
};

export default function(state = initialState, action) {
  switch (action.type) {
    case GET_HEALTHDATA:
      return {
        ...state,
        healthData: [...action.payload],
        loading: false
      };

index. js

const rootReducer = combineReducers({
  router: connectRouter(history),
  item: itemReducer,
  error: errorReducer,
  auth: authReducer,
  fatLog: fatLogReducer,
  register: registerReducer,
  loading: loadingReducer,
  healthData: healthDataReducer
});
export default rootReducer;

Затем я могу отобразить эти данные следующим образом:

class DailyCalorieCalc extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weight: "1",
      height: "1",
      activityLevel: "1",
      goal: "1"
    };
  }

  static propTypes = {
    isAuthenticated: PropTypes.bool,
    healthData: PropTypes.object,
    user: PropTypes.object
  };

  componentDidMount() {
    //const { healthData, username } = this.props;
    this.props.getHealthData(this.props.user.name);
  }

  render() {
    const { healthData } = this.props;
    return (
      <div>
        <div>Welcome {this.props.user.name}</div>

        {healthData.map(healthData => {
          return (
            <div className="tableBox">
              <div className="hlthDataCol">
                <div className="label">Sex</div>
                <div className="data">{healthData.sex}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Weight</div>
                <div className="data">{healthData.weight}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Height</div>
                <div className="data">{healthData.height}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Activity Level</div>
                <div className="data">{healthData.activityLevel}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Goal</div>
                <div className="data">{healthData.goal}</div>
              </div>
            </div>
          );
        })}
      </div>
    );
  }
}

const mapStateToProps = state => ({
  isAuthenticated: state.auth.isAuthenticated,
  user: state.auth.user,
  healthData: state.healthData.healthData
});

export default connect(mapStateToProps, {
  getHealthData
})(DailyCalorieCalc);

НО , Я бы предпочел изменить свое хранилище Redux так, чтобы healthData представлял собой всего лишь один объект (если он работал, но это не так):

const initialState = {
  healthData: {},
  loading: false,
  sex: "",
  age: "",
  height: "",
  weight: "",
  goal: "",
  activityLevel: ""
};

export default function(state = initialState, action) {
  switch (action.type) {
    case GET_HEALTHDATA:
      return {
        ...state,
        healthData: action.payload,
        loading: false
      };

Затем я хочу иметь возможность устанавливать значения объект к локальному состоянию моего компонента в componentDidUpdate. Примерно так:

class DailyCalorieCalc extends Component {
  constructor(props) {
    super(props);
    this.state = {
      weight: "1",
      height: "1",
      activityLevel: "1",
      goal: "1"
    };
  }

  static propTypes = {
    isAuthenticated: PropTypes.bool,
    healthData: PropTypes.object,
    user: PropTypes.object
  };

  componentDidMount() {
    //const { healthData, username } = this.props;
    this.props.getHealthData(this.props.user.name);
  }

  componentDidUpdate(prevProps, prevState) {
    const { error, healthData } = this.props;
    if (healthData != pervProps.healthData){
      this.setState({
        weight: healthData.weight, 
        height: healthData.height, 
        age: healthData.age,
        goal: healthData.goal, 
        activityLevel: healthData.activityLevel
      })
    } 
    }

  render() {
    const { healthData } = this.props;
    return (
      <div>
        <div>Welcome {this.props.user.name}</div>

        {healthData.map(healthData => {
          return (
            <div className="tableBox">
              <div className="hlthDataCol">
                <div className="label">Sex</div>
                <div className="data">{healthData.sex}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Weight</div>
                <div className="data">{healthData.weight}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Height</div>
                <div className="data">{healthData.height}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Activity Level</div>
                <div className="data">{healthData.activityLevel}</div>
              </div>
              <div className="hlthDataCol">
                <div className="label">Goal</div>
                <div className="data">{healthData.goal}</div>
              </div>
            </div>
          );
        })}
      </div>
    );
  }
}

const mapStateToProps = state => ({
  isAuthenticated: state.auth.isAuthenticated,
  user: state.auth.user,
  healthData: state.healthData.healthData
});

export default connect(mapStateToProps, {
  getHealthData
})(DailyCalorieCalc);

Как мне перевести значения, хранящиеся в моем объекте данных, в локальное состояние? Заранее спасибо. Приношу свои извинения за такой длинный и беспорядочный вопрос.

...