过滤javascript中的嵌套数组而不影响引用

过滤javascript中的嵌套数组而不影响引用,javascript,arrays,reactjs,next.js,Javascript,Arrays,Reactjs,Next.js,第一个职位 我正在使用next.js,并创建了一个过滤帖子的函数。如果在数组(例如ObjChild)中未经验证地收集帖子,则效果良好。在我的网站的另一个部分,我有一个父帖子数组,每个帖子中都有一个子帖子数组。当我在我的站点的任何部分过滤帖子时,它会影响整个站点,并且我无法返回到原始数组,我可以在简化版本中使用setState(原始) 数据结构示例: // Collection Index File const Collection = [ ObjParent1: {

第一个职位

我正在使用next.js,并创建了一个过滤帖子的函数。如果在数组(例如ObjChild)中未经验证地收集帖子,则效果良好。在我的网站的另一个部分,我有一个父帖子数组,每个帖子中都有一个子帖子数组。当我在我的站点的任何部分过滤帖子时,它会影响整个站点,并且我无法返回到原始数组,我可以在简化版本中使用setState(原始)

数据结构示例:


// Collection Index File

const Collection = [
    ObjParent1: {
        id: 'abc'
        info: 'abc'
        children: [
            ObjChild1 {
            idchild: 'abc'
            infochild: 'abc'
            tags: ['tag1', 'tag2', 'tag3']
            },
            ObjChild2 {
            idchild: 'abc'
            infochild: 'abc'
            tags: ['tag1', 'tag2', 'tag3']
            },
            ObjChild-n {
            idchild: 'abc'
            infochild: 'abc'
            tags: ['tag1', 'tag2', 'tag3']
            }
        ]
    },  
    ObjParent2: {
        id: 'abc'
        info: 'abc'
        children: [
            objChild1 {
            idchild: 'abc'
            infochild: 'abc'
            tags: ['tag1', 'tag2', 'tag3']
            }
        ]
    },  
    ObjParent3: {
        id: 'abc'
        info: 'abc'
        children: [
            objChild1 {
            idchild: 'abc'
            infochild: 'abc'
            tags: ['tag1', 'tag2', 'tag3']
            }
        ]
    }   
]

我认为我的问题与深度嵌套数组有关,首先,它是一个浅数组,因此array.map返回一个新的基元值数组。在嵌套示例中,ObjChild仍然保存引用值。我该怎么做?我尝试使用array.splice(),但没有任何更改。我以为通过分配一个新的成本,我克服了这一点,但事实证明,这只是更多的参考

示例代码:


// Page.js

const postFilter = (collection, tag) => {
    const newarray = collection
    newarray.map((objParent) => {
        objParent.children = objParent.children.filter(({tags}) => {
            return (tags.find(element => element == tag)) ? true : false
        });
    });
    return newarray
};

function Page(Collection) {
    const [posts, setPosts] = useState(Collection);
    
    function filterPosts(clicked) {
        const tag = clicked.currentTarget.value
        setPosts(postFilter(posts, tag))
    }
    
    return (
        posts.map( //...... maps Collection
            <button value='tag' onClick={filterPosts}>button</button>
    )
}


谢谢你的帮助!(如果有更简单的方法问这个问题,请告诉我)

我将输入改写为正确的格式。我假设过滤器是我们有一个标签,如果标签中的任何项目没有该标签,问题将从列表中过滤掉

您可以检查下面的实现

const originObj=[
{
id:‘abc’,
信息:“abc”,
儿童:[
{
idchild:'abc',
infochild:'abc',
标记:['tag2','tag3'],
},
{
idchild:'abc',
infochild:'abc',
标签:['tag1','tag3'],
},
{
idchild:'abc',
infochild:'abc',
标签:['tag1','tag5','tag3'],
}
]
},
{
idchild:'ddd',
infochild:'abc',
标签:['tag1','tag5','tag3'],
}
]
常量过滤器号=(项目,标记)=>{
退货项目.标签.包括(标签)
}
const recursiveFind=(项目、标记)=>{
返回项目。减少((acc,cur)=>{
如果(!cur.children | | cur.children.length==0){
if(过滤器Fn(电流,标签)){
附件推送(当前)
}
}否则{
const newCur={…cur,children:[…recursiveFind(cur.children,tag)]}
acc.push(新电流)
}
返回acc
},[])
}
常量标记='tag5'
const newObj=递归查找(originObj,标记)
console.log(newObj)
console.log(originObj)
问题 您正在更改您的状态对象。除此之外,您不会从更新状态的
postFilter
实用程序返回新的数组引用。将引用映射到您的
posts
状态,并修改
子属性

const postFilter = (collection, tag) => {
  const newarray = collection; // <-- reference to posts state

  // no capture of mapped result
  newarray.map((objParent) => {
    // objParent.children property mutation
    objParent.children = objParent.children.filter(({tags}) => {
      return (tags.find(element => element == tag)) ? true : false
    });
  });

  return newarray; // <-- still same posts reference
};
我建议也使用功能状态更新,这样可以确保
posts
状态从以前的状态正确更新。这是一个小小的调整

function filterPosts(clicked) {
  const tag = clicked.currentTarget.value
  setPosts(posts => postFilter(posts, tag))
}
const集合=[
{
id:“abc”,
信息:“abc”,
儿童:[
{
idchild:“abc”,
信息儿童:“abc”,
标签:[“tag1”、“tag2”、“tag3”]
},
{
idchild:“abc”,
信息儿童:“abc”,
标签:[“tag1”、“tag4”、“tag5”]
},
{
idchild:“abc”,
信息儿童:“abc”,
标签:[“tag6”、“tag7”、“tag8”]
}
]
},
{
id:“abc”,
信息:“abc”,
儿童:[
{
idchild:“abc”,
信息儿童:“abc”,
标签:[“tag1”、“tag2”、“tag3”]
}
]
},
{
id:“abc”,
信息:“abc”,
儿童:[
{
idchild:“abc”,
信息儿童:“abc”,
标签:[“tag4”、“tag2”、“tag3”]
}
]
}
];
const postFilter=(集合、标记)=>{
返回collection.map(objParent=>({
…显然,
childrent:objParent.children.filter(({tags})=>tags.includes(tag))
}));
};
const result=postFilter(集合“tag1”);

控制台日志(结果)
您可以共享您的输入和预期输出吗?
array.map
array.filter
都会返回新的数组引用,因此不清楚您是否正在执行其他操作以改变数据。
postFilter
函数中的代码也不正确。您只是返回
postarray
值,我想您的意思是返回
newarray.map
的结果。
proj.challenges
对象是什么?您在
postFilter
回调中使用一些筛选结果对其进行变异,即
proj.challenges=proj.challenges.filter(…)
@NghiNguyen输入与示例类似,我将添加一个示例输出。@drewrese不完全相同,array.map只进行浅拷贝,因此。challenges继续包含引用。当我修改它时,我会修改被引用的对象。我会更新这个例子,当我试图让它更具可复制性时,我混淆了一些东西。汉克斯,我会去测试一下。我确实有一个标记的状态,但那个位正在工作,所以我省略了它。你能详细介绍一下这个语法吗?我以前没有遇到过它(非常新)
setPosts(posts=>postFilter(posts,tag))
另外,我还没有完全确定spread,通过使用…objParent,它可以传播obj parent,这样你就可以直接访问子对象了?@jsmccid-Sure
setPosts(posts=>postFilter(posts,tag))
在更新依赖于以前的状态时使用。在这种情况下,依赖关系是前一个
posts
state数组,因为我们必须将其浅层复制到下一个state对象中(这也是
postFilter
回调中使用的扩展语法)。当浅层复制任何正在更新的嵌套状态属性时,会使用扩展语法,以使其具有新的对象引用,并且可以工作。React使用浅对象相等。
const postFilter = (collection, tag) => {
  return collection.map(objParent => ({
    ...objParent,
    children: objParent.children.filter(({ tags }) => tags.includes(tag))
  }));
};
function filterPosts(clicked) {
  const tag = clicked.currentTarget.value
  setPosts(posts => postFilter(posts, tag))
}