【问题标题】:React - Redux component not displaying array.length correctly despite component being rerendered on state change without mutating the stateReact - Redux 组件未正确显示 array.length,尽管组件在状态更改时重新渲染而不改变状态
【发布时间】:2020-01-30 06:48:09
【问题描述】:

问题:我正在使用 React 和 Redux 存储来管理我的状态。我想在组件上显示过滤器。这些筛选器将从 Tableau Javascript API 返回。根据 Tableau JavaScriptAPI 的返回,我正在更新商店中的状态。状态正在使用正确的过滤器正确更新,这也导致我的组件更新/重新渲染。到目前为止一切都很好。

但是当我尝试从 state.props 访问这些过滤器(无论是使用 Object.keys() 的对象还是使用 array.length 的数组)时,我会得到空数组作为回报。

这可能是由于错误地使用了 Thunk/Async Await。

这里是代码sn-p

第 1 步:从 React 调用操作。当我单击按钮时,会调用获取仪表板操作

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

第 2A 步:这里是 fetchDashboard 操作: 在此操作中,我正在创建要在组件上显示的 filterNAmes 数组。当我的操作向 Tableau JavascriptAPI 发送 API 请求时,我在这里唱着 Thunk。我希望它工作的方式是一次,我们从 API 获得响应,我们将把 viz 分派给 reducer,并将 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;
};

这会正确更新 store 中的 State fetchFilter。

第四步:使用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。 这不允许我在屏幕上显示数组的内容。

要阅读的内容很多,但我无法将其放在较小的描述中。 如果我需要添加更多详细信息,请告诉我。

提前感谢所有帮助:)

【问题讨论】:

    标签: reactjs redux react-redux redux-thunk


    【解决方案1】:

    这里发生了很多事情,可能是与 Tableau 集成的更好方法,但为了解决您的问题,我认为您只需在您的 fetchDashboard 操作中将 dispatch(fetchFilter(filterNames)); 移动到 then() 块内。

    .then(function(filters) {
      // all that other code ...
      dispatch(fetchFilter(filterNames));
    });
    

    【讨论】:

    • 感谢您的回复。它不工作。调度永远不会被执行,尝试添加一个 console.log() 并且它根本没有执行。在下一条评论中添加 sn-p
    • .then(function(filters) { for (let filter in filters) { let filterTitle = filters[filter].getFieldName(); let filterName = {}; filterName[filterTitle] = [];让 len = filters[filter].getAppliedValues().length; for (let i = 0; i
    【解决方案2】:

    fetchDashboard 中,您可以尝试将dispatch(fetchFilter(filterNames)); 移动到onFirstInteractive 函数的末尾。

    new window.tableau.Viz(vizContainer, url, options) 不是异步操作,这意味着您使用空数组调度 fetchFilterconsole.log 在这种情况下没有帮助,请参阅 here)。

    【讨论】:

      猜你喜欢
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 1970-01-01
      相关资源
      最近更新 更多