Реакция - компонент Redux неправильно отображает массив - PullRequest
1 голос
/ 01 октября 2019

Проблема: я использую React с хранилищем Redux для управления своим состоянием. Я хочу отобразить фильтры на компоненте. Эти фильтры будут возвращены из API таблиц Javascript. На основании возврата из таблицы JavaScriptAPI я обновляю состояние в магазине. Состояние корректно обновляется с правильными фильтрами, что также вызывает обновление / повторную визуализацию моего компонента. Пока все хорошо.

Но когда я пытаюсь получить доступ к этим фильтрам (будь то объект с помощью Object.keys () или массив с помощью array.length) из state.props, я получаю нулевой массив в ответ.

Вероятно, это связано с неправильным использованием Thunk / Async Await.

Вот фрагмент кода

Шаг 1. Вызов действия из React. Когда я нажимаю кнопку, вызывается действие панели инструментов

class DashboardView extends Component {
  componentDidMount() {
    id = this.props.dashboardDetails.categoryID;
    console.log("Mounted");
    this.props.fetchDashboard(
      this.props.dashboardDetails.categoryURL,
      this.vizContainer
    );
  }

Шаг 2А: Вот действие fetchDashboard: В рамках этого действия я создаю массив filterNAmes, который я хочу отобразить в моем компоненте. Я напеваю Thunk здесь, так как мои действия отправляют запрос API в Tableau JavascriptAPI. То, как я хочу, чтобы это работало, один раз, мы получаем ответ от API, мы отправляем viz редуктору и массив filterNames другому действию fetchFilter. Фрагмент прилагается.

export const fetchDashboard = (url, vizContainer) => async dispatch => {
  let filterNames = [];
  //  let titlesTemp = {};
  //const vizContainer = {};
  const options = {
    hideToolbar: true,
    onFirstInteractive: function() {
      let workbook = viz.getWorkbook();
      const activeSheet = workbook.getActiveSheet();
      activeSheet
        .getWorksheets()
        .get("Index")
        .getFiltersAsync()
        .then(function(filters) {
          for (let filter in filters) {
            let filterTitle = filters[filter].getFieldName();
            let filterName = {};
            filterName[filterTitle] = [];
            let len = filters[filter].getAppliedValues().length;
            for (let i = 0; i < len; i++) {
              filterName[filterTitle].push(
                filters[filter].getAppliedValues()[i].value
              );
            }
            filterNames.push(filterName);
          }
        });
    }
  };
  let viz = await new window.tableau.Viz(vizContainer, url, options);
  dispatch({ type: "FETCH_DASHBOARD", payload: { viz } });
  console.log(filterNames, filterNames.length);
  return dispatch(fetchFilter(filterNames));
};

Когда я console.log (filterNames, filterNames.length), в массиве filterNames есть элементы (которые оцениваются позже), но filterNames.length возвращает 0. Я думаю, что это основная причинавопроса. Я хочу отправить следующее действие только при заполнении FilterNames.

Шаг 2B:

export const fetchFilter = filterNames => {
  console.log("FETCH_FILTER action called", filterNames);
  return { type: "FETCH_FILTER", filterNames };
};

Предполагается, что это не проблема- Шаг 3: Редуктор

const fetchFilterReducer = (fetchFilter = [], action) => {
  if (action.type === "FETCH_FILTER") {
    console.log("fetchfilterreducercalled:", action.filterNames);
    return action.filterNames;
  }
  return fetchFilter;
};

Это корректно обновляет состояние fetchFilter в хранилище.

Шаг 4: Используя функцию connect, я извлекаю массив fetchFilter в свойстве компонента.

class FilterDisplay extends React.Component {
  componentDidMount() {
    console.log(this.props);
    if (this.props.selectionFilters.length !== 0) {
      console.log(this.props);
    }
  }

  componentDidUpdate() {
    console.log(this.props.selectionFilters.length);
    if (this.props.selectionFilters.length !== 0) {
      console.log("filter display updated");
      console.log(this.props);     
    }
  }

  render() {
    return <div>hey</div>; //<Tile></Tile>;
  }
}

const mapStateToProps = state => {
  console.log("first  filters in state:", state.fetchFilter);

  return {
    selectionFilters: state.fetchFilter
  };
};
export default connect(mapStateToProps)(FilterDisplay);

На моем componentDidUpdate длина массива selectionFilters равна 0. Это не позволяет мне отображать содержимое массива на моем экране.

Это много для чтения, но я не могу его уместитьв меньшем описании. Пожалуйста, дайте мне знать, если мне нужно добавить больше деталей.

Заранее спасибо за помощь:)

Ответы [ 2 ]

0 голосов
/ 01 октября 2019

В fetchDashboard вы можете попытаться переместить dispatch(fetchFilter(filterNames)); в конце функции onFirstInteractive.

new window.tableau.Viz(vizContainer, url, options) не является асинхронной операцией, что означает, что вы отправляете fetchFilterс пустым массивом (console.log в этом случае не помогает, см. здесь ).

0 голосов
/ 01 октября 2019

Здесь много чего происходит и, возможно, лучший способ интеграции с Tableau, но для решения вашей проблемы, я думаю, вам просто нужно переместить dispatch(fetchFilter(filterNames)); внутри блока then() в вашем действии fetchDashboard.

.then(function(filters) {
  // all that other code ...
  dispatch(fetchFilter(filterNames));
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...