Reactjs 使用useState和useEffect筛选处于状态的项目列表中的项目

Reactjs 使用useState和useEffect筛选处于状态的项目列表中的项目,reactjs,typescript,react-redux,react-hooks,Reactjs,Typescript,React Redux,React Hooks,我在我的应用程序上有一个项目列表,我正在尝试为每个项目创建一个详细信息页面。此外,我没有管理如何使用useState和useEffect使用typescript,我可以管理使用componentDidMount,这不是我的目标 在我的状态中,称为MetricState,我有“metrics”,我在一些地方看到,我也应该在我的状态中添加一个“selectedMetric”。我认为这是一个奇怪的解决方案,因为我只想能够通过“在状态为的度量列表上选择id为x的度量”的操作来调用调度。 这是codesa

我在我的应用程序上有一个项目列表,我正在尝试为每个项目创建一个详细信息页面。此外,我没有管理如何使用useState和useEffect使用typescript,我可以管理使用componentDidMount,这不是我的目标

在我的状态中,称为
MetricState
,我有
“metrics”
,我在一些地方看到,我也应该在我的状态中添加一个
“selectedMetric”
。我认为这是一个奇怪的解决方案,因为我只想能够通过“在状态为的度量列表上选择id为x的度量”的操作来调用调度。

这是codesandbox,当您单击“详细信息”按钮时,您将看到它没有打印来自该州的所选度量的名称:

这是我的状态:

export type MetricState = {
  metrics: IMetric[];
};
调度调用的我的actionCreators.js文件

export function fetchMetric(catalog, metricId) {
  const action = {
    type: ACTION_TYPES.CHOOSE_METRIC,
    payload: []
  };
  return fetchMetricCall(action, catalog, metricId);
}

const fetchMetricCall = (action, catalog, metricId) => async (dispatch) => {
  dispatch({
    type: action.type,
    payload: { metrics: [catalog.metrics.filter((x) => x.name === metricId)] } //contains the data to be passed to reducer
  });
};
最后是MetricsDeatail.tsx页面,在该页面中,我尝试使用来自路线参数的id筛选所选项目:

const metricId = props.match.params.metricId;
  const catalog = useSelector<RootState, MetricState>(
    (state) => state.fetchMetrics
  );

  const selectedMetric: IMetric = {
    name: "",
    owner: { team: "" }
  };
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(appReducer.actionCreators.fetchMetric(catalog, metricId));
  }, []);
const metricId=props.match.params.metricId;
常量目录=使用选择器(
(state)=>state.fetchMetrics
);
常数selectedMetric:Metric={
姓名:“,
所有者:{团队:}
};
const dispatch=usedpatch();
useffect(()=>{
分派(appReducer.actionCreators.fetchMetric(catalog,metricId));
}, []);
在我的州,称为MetricState,我有“metrics”,我在一些地方看到,我也应该在我的州中添加一个“selectedMetric”。我认为这是一个奇怪的解决方案,因为我只希望能够通过“在状态为的度量列表上选择id为x的度量”的操作调用分派

我同意你的看法。
metricId
通过
props
来自URL,因此它也不需要处于该状态。您希望每个数据都有一个“单一的真相来源”

为了使用此设计模式,您的Redux商店需要能够:

  • 根据度量的id获取并存储单个度量
  • 根据存储的id从存储中选择度量
我通常发现使用键控对象状态(
Record
)会更容易,但是
数组也可以

您的组件应该如下所示:

const MetricDetailsPage: React.FC<MatchProps> = (props) => {
  const metricId = props.match.params.metricId;

  // just select the one metric that we want
  // it might be undefined initially
  const selectedMetric = useSelector<RootState, IMetric | undefined>(
    (state) => state.fetchMetrics.metrics.find(metric => metric.name === metricId )
  );

  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(appReducer.actionCreators.fetchMetric(metricId));
  }, []);

  return (
    <div>
      <Link to={`/`}>Go back to main page</Link>
      Here should print the name of the selected metric:{" "}
      <strong>{selectedMetric?.name}</strong>
    </div>
  );
};

export default MetricDetailsPage;
const MetricDetailsPage:React.FC=(道具)=>{
const metricId=props.match.params.metricId;
//只需选择我们想要的一个指标
//它最初可能没有定义
常量selectedMetric=useSelector(
(state)=>state.fetchMetrics.metrics.find(metric=>metric.name==metricId)
);
const dispatch=usedpatch();
useffect(()=>{
分派(appReducer.actionCreators.fetchMetric(metricId));
}, []);
返回(
返回主页
此处应打印所选度量的名称:{“”}
{selectedMetric?.name}
);
};
导出默认MetricDetailsPage;

但是您应该重新处理动作创建者,这样您就不会在组件中选择整个
目录
,然后将其作为参数传递给动作创建者。

嗨,琳达!谢谢你的帮助!我还有一个问题。在您的fakeApi上,您正在调用“数据”,但在我的例子中,我希望获取存储中的数据,因为我的数据不会在实际应用程序上被模拟。有什么建议吗?:)我可以使用您解释过的useSelector的一部分来检索度量,它可以工作,但我想分派一个操作,直接在actionCreators.js上对状态执行此筛选。如果存储中已经存在数据,则无需分派任何操作。其思想是,状态将存储所有以前加载的度量,因此如果从“/one”更改为“/two”,则不需要更改存储中的任何内容。但当您处理react路由器时,您需要使其能够独立加载每个页面。您不能指望在登录“/one”之前已加载完整列表。这就是为什么我认为会有一些API调用加载单个度量。