.reduce(reducer): Optic
tsOptic<T, mapped>.reduce(reducer: (values: ReduceValue<T>[]) => ReduceValue<T>[]): Optic<T, mapped>;Optic<T, mapped>.reduce(reducer: (values: ReduceValue<T>[]) => ReduceValue<T> | undefined): Optic<T, partial>;
tsOptic<T, mapped>.reduce(reducer: (values: ReduceValue<T>[]) => ReduceValue<T>[]): Optic<T, mapped>;Optic<T, mapped>.reduce(reducer: (values: ReduceValue<T>[]) => ReduceValue<T> | undefined): Optic<T, partial>;
The reduce method is available on mapped optics and lets you derive a new optic focused on one of the values of the mapped optic, or several of them.
It effectively lets you sort, filter, or slice the values you mapped over and get an optic focused on the result.
More informations here: Map/Reduce
Example:
tsximport {createState } from "@optics/react";consttodosOptic =createState ([{name : "Handle promises",done : false },{name : "Fix type error",done : true },{name : "Finish docs",done : false },{name : "Add tests",done : true },]);// focused on every ongoing todoconstongoingTodosOptic =todosOptic .map ().reduce ((todos ) =>todos .filter ((todo ) => !todo .value .done ));ongoingTodosOptic .get ();// [{ name: "Handle promises", done: false }, { name: "Finish docs", done: false }]// sort by done status, then by nameconstsortedTodosOptic =todosOptic .map ().reduce ((todos ) =>[...todos ].sort ((a ,b ) => {constboolOrder =Number (a .value .done ) -Number (b .value .done );returnboolOrder === 0?a .value .name .localeCompare (b .value .name ):boolOrder ;}));sortedTodosOptic .get ();// [// { name: "Handle promises", done: false },// { name: "Finish docs", done: false },// { name: "Add tests", done: true },// { name: "Fix type error", done: true },// ]ongoingTodosOptic .name .set ((prev ) =>prev .toUpperCase ());sortedTodosOptic .get ();// [// { name: "FINISH DOCS", done: false },// { name: "HANDLE PROMISES", done: false },// { name: "Add tests", done: true }// { name: "Fix type error", done: true },// ]
tsximport {createState } from "@optics/react";consttodosOptic =createState ([{name : "Handle promises",done : false },{name : "Fix type error",done : true },{name : "Finish docs",done : false },{name : "Add tests",done : true },]);// focused on every ongoing todoconstongoingTodosOptic =todosOptic .map ().reduce ((todos ) =>todos .filter ((todo ) => !todo .value .done ));ongoingTodosOptic .get ();// [{ name: "Handle promises", done: false }, { name: "Finish docs", done: false }]// sort by done status, then by nameconstsortedTodosOptic =todosOptic .map ().reduce ((todos ) =>[...todos ].sort ((a ,b ) => {constboolOrder =Number (a .value .done ) -Number (b .value .done );returnboolOrder === 0?a .value .name .localeCompare (b .value .name ):boolOrder ;}));sortedTodosOptic .get ();// [// { name: "Handle promises", done: false },// { name: "Finish docs", done: false },// { name: "Add tests", done: true },// { name: "Fix type error", done: true },// ]ongoingTodosOptic .name .set ((prev ) =>prev .toUpperCase ());sortedTodosOptic .get ();// [// { name: "FINISH DOCS", done: false },// { name: "HANDLE PROMISES", done: false },// { name: "Add tests", done: true }// { name: "Fix type error", done: true },// ]
You can also focus back on a single value, which will yield a partial optic.
tsxconstfirstDoneTodoOptic =todosOptic .map ().reduce ((todos ) =>todos .find ((todo ) =>todo .value .done ));firstDoneTodoOptic .get ();// { name: "Fix type error", done: true }
tsxconstfirstDoneTodoOptic =todosOptic .map ().reduce ((todos ) =>todos .find ((todo ) =>todo .value .done ));firstDoneTodoOptic .get ();// { name: "Fix type error", done: true }