在调度之间检测到状态突变,在路径 `...` 中。这可能会导致不正确的行为

达克斯

我的父组件中有一个列表和日历视图组件。对于日历组件,我希望能够将搜索过滤器推送到我的 url 以过滤掉未选择的位置。我正在尝试根据我提供给我的 queryString 函数的参数生成一个查询字符串,但是当我将 queryString 推送到我的 url 时,我收到以下错误:

在调度之间检测到状态突变,在路径中locations.calendarLocationList.0这可能会导致不正确的行为。http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments

我不确定是什么原因造成的,因为在此过程中我没有触及状态。

父组件、渲染列表和日历视图

class LocationShell extends Component<
  LocationShellProps & WithNamespaces & RouteComponentProps,
  LocationShellState
  > {
  constructor(props: LocationShellProps & WithNamespaces & RouteComponentProps) {
    super(props);

    this.state = {
      isCalendarView: false,
      open: false,
      locationIdToDelete: -1,
      activePage: 1,
      activeSortHeader: undefined,
      direction: 'ascending',
      searchValue: undefined
    };
  }

  componentDidMount = (
    { loadLocations, loadSessionLocations, loadCalendarListLocations } = this.props,
    { activePage } = this.state
  ) => {
    loadLocations({ page: activePage });
    loadSessionLocations();
    loadCalendarListLocations();
  };

  toggleView = () => {
    const { isCalendarView } = this.state;
    this.setState((prevState) => ({
      ...prevState,
      isCalendarView: !isCalendarView
    }))
  }

  renderListView = () => {
    const { locationStatus, locations, selectedLocationId, history, match, pages, t } = this.props;
    const { activePage, activeSortHeader, direction } = this.state;

    switch (locationStatus) {
      case ProgressStatus.InProgress:
        return <InitialLoader />
      case ProgressStatus.Done:
        return (
          <DataTableWrapper
            // props
          />
        )
      case ProgressStatus.Error:
        return <NoDataFound />
      case ProgressStatus.Uninitialized:
        return null
    }
  }

  renderCalendarView = ({ calendarListStatus, sessionLocations, calendarListLocations } = this.props) => {
    switch (calendarListStatus) {
      case ProgressStatus.InProgress:
        return <InitialLoader />
      case ProgressStatus.Done:
        const events = toLocationEvents(sessionLocations!);
        return <CalendarView {...this.props} events={events} items={calendarListLocations!} name={'locations'} />
      case ProgressStatus.Error:
        return <NoDataFound />
      case ProgressStatus.Uninitialized:
        return null
    }
  }

  render() {
    const { pathName, t } = this.props;
    const { isCalendarView } = this.state;
    return (
      <Fragment>
        <PageHeader
          breadCrumbParts={split(pathName, '/').map(x => t(x))}
          title={t('moduleTitle')}
        />
        <Button.Group size="mini" style={{ padding: '10px 5px 10px 0px' }}>
          <Button positive={!isCalendarView} onClick={this.toggleView}>Lijst</Button>
          <Button.Or />
          <Button positive={isCalendarView} onClick={this.toggleView}>Kalender</Button>
        </Button.Group>
        <Button
          positive
          icon='add'
          size="mini"
          labelPosition='right'
          content="Nieuwe locatie"
          onClick={() => this.props.history.push(this.props.match.path + '/create')}
        />
        {isCalendarView ? this.renderCalendarView() : this.renderListView()}
      </Fragment>
    );
  }
}

const mapStateToProps = (state: GlobalState) => {
  return {
    locations: getLocations(state.locations),
    calendarListLocations: state.locations.calendarLocationList,
    calendarListStatus: state.locations.calendarListStatus,
    sessionLocations: state.locations.sessionLocations,
    selectedLocation: getSelectedLocation(state.locations),
    selectedLocationId: getSelectedLocationId(state.locations),
    pages: getAmountPages(state.locations),
    locationStatus: state.locations.locationStatus,
    sessionLocationStatus: state.locations.sessionLocationStatus,
    pathName: getPathName(state.router)
  };
};

const mapDispatchToProps = (dispatch: Dispatch) => ({
  loadLocations: (queryParams: QueryParams) =>
    dispatch(FetchLocations(queryParams)),
  loadSessionLocations: () => dispatch(FetchTrainingSessionLocations({})),
  loadCalendarListLocations : () => dispatch(FetchCalendarListLocations({})),
  clearLocations: () => dispatch(ClearLocations()),
  deleteLocation: (id: number) => dispatch(DeleteLocation({ locationId: id }))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(withNamespaces('locations')(LocationShell));

renderCalendarView() 正在呈现我的日历组件

我的日历组件:

interface CalendarViewState {
    selectedIds: number[];
}

type CalendarViewProps = {
    events: CalendarEvent[];
    name: string;
    items: CalendarListLocation[];
    navigatePush: (values: string) => void;
} & RouteComponentProps

class CalendarView extends Component<CalendarViewProps & WithNamespaces, CalendarViewState> {

    state: CalendarViewState = {
        selectedIds: []
    }

    componentDidMount = () => {
        const { events, items } = this.props;
        const { baseUrl, newEntity } = moduleConstants;
        this.setState((prevState) => ({
            ...prevState,
            selectedIds: items.map(x => x._id)
        }), () => {
            updateQueryString(this.props, { page: 1, locations: [1, 2] })
        }
        )
    }

    queryParams(props: CalendarViewProps = this.props) {
        return queryParams<QueryParams>(props.location.search);
    }
    componentDidUpdate = (prevProps: CalendarViewProps, prevState: CalendarViewState) => {
        const { selectedIds } = this.state;
        console.log()
        if (!isEqual(prevState.selectedIds, selectedIds)) {
            console.log(this.queryParams())
        }
    }
    handleChange = (id: number) => {
        const { selectedIds } = this.state;
        this.setState((prevState) => ({
            ...prevState,
            selectedIds: (selectedIds.includes(id) ? selectedIds.filter(x => x !== id) : [...selectedIds, id])
        }));
    };

    render() {
        const { events, name, t, items } = this.props
        return (
            <Grid divided="vertically" padded>
                <Grid.Row columns={2}>
                    <Grid.Column width={4}>
                        <CalendarSelectionList
                            name={t(name)}
                            onSelectionChange={this.handleChange}
                            selectedIds={this.state.selectedIds}
                            locations={items.sort((a: CalendarListLocation, b: CalendarListLocation) => a.name.localeCompare(b.name))}
                        />
                    </Grid.Column>
                    <Grid.Column width={12}>
                        <div style={{ height: '800px' }}>
                            <Calendar
                                events={events.filter(x => this.state.selectedIds.includes(x.id))}
                            />
                        </div>
                    </Grid.Column>
                </Grid.Row>
            </Grid>
        );
    }
}

const mapDispatchToProps = (dispatch: Dispatch) => ({
    navigatePush: (path: string) => dispatch(push(path))
});

export default connect(
    null,
    mapDispatchToProps
)(withNamespaces(['calendar'])(CalendarView));

updateQueryString(this.props, { page: 1, locations: [1, 2] }) 被触发,此函数将使用生成的 queryString 更新 url

export function queryParams<T>(search: string) {
  return (queryString.parse(search) as unknown) as T;
}

export function updateQueryString<T>(props: RouteComponentProps, newValues: T) {
  const currentQuery = queryParams<T>(props.location.search);
  const newProps = Object.assign(currentQuery, newValues);
  props.history.push({
    pathname: props.location.pathname,
    search: queryString.stringify(filterSearchResults(newProps))
  });
}
function filterSearchResults(values: any) {
  let obj: any = {};
  Object.keys(values).forEach(
    key => values[key] && (obj[key] = values[key])
  );
  return obj;
}

在此之后,出现上述错误。为什么会出现这个错误?

这将是烧瓶

错误意味着它locations.calendarLocationList发生了变化,而 Redux 存储应该是不可变的。

calendarLocationList被用作itemsinCalendarView和 mutated withitems.sort(...)因为数组会sort改变现有数组而不是创建一个新数组。

这可以通过[...items].sort(...).

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在调度中检测到状态突变:即使使用工具包

在对象的React redux状态数组中,我无法更新其创建错误的状态在分派之间检测到状态突变

[Vue警告]:检测到重复的密钥:x。这可能会导致更新错误

无法修复警告检测到重复键:“ 0”。这可能会导致更新错误

Ag-grid:从getRowNodeId回调中检测到重复的节点ID 107,这可能会导致网格出现问题

vue.js检测到重复的密钥:“ topic.ID”。这可能会导致更新错误。怎么了

输出流中先前电流的非单调DTS更改为这可能会导致输出文件中的时间戳不正确

在调度之间检测到状态突变,但我尚未改变状态

React和Redux:未捕获错误:在调度之间检测到状态突变

未捕获的不变违反:使用arrayMove时在两次调度之间检测到状态突变

在调度、Redux 工具包和选择器/重新选择之间检测到状态突变

[Vue警告]:检测到重复的密钥:x。这可能会导致更新错误。如何防止添加已通过方法添加的项目

Convert.ToDouble中的空值行为不正确,这可能吗?

SQL可能会导致循环或多个级联路径

FK约束可能会导致循环或多个级联路径

大小不正确的GUI。Qt Designer中可能会滥用布局

类对象的数组元素设置不正确,set()和get()成员函数可能会导致

在模板中调用 FileField 对象会呈现不正确的路径

Java路径中的斜杠不正确

Facebook Buck:建立失败:未检测到本机平台。Android NDK可能配置不正确

SimpleDateFormat.parse 未检测到不正确的日期

从行中删除下拉列表和文本字段会删除ReactJS中状态更改的不正确字段

在表 'Y' 上引入 FOREIGN KEY 约束 'X' 可能会导致循环或多个级联路径

引入FOREIGN KEY约束可能会导致循环或多个级联路径

引入FOREIGN KEY约束可能会导致循环或多个级联路径-为什么?

SQL Server 引入 FOREIGN KEY 约束可能会导致循环或多个级联路径

外键约束可能会导致循环或多个级联路径?

EF Core DeleteBehavior.Cascade可能会导致循环或多个级联路径

FOREIGN KEY可能会导致循环或多个级联路径异常