Javascript 如何在Reactjs的菜单中设置onClick函数?

Javascript 如何在Reactjs的菜单中设置onClick函数?,javascript,json,reactjs,recursion,Javascript,Json,Reactjs,Recursion,抱歉,如果这是一个愚蠢/明显的问题,我是Javascript/React新手。我正在尝试创建一个菜单,其中包含从API调用中获取的JSON对象。由于JSON数据是一组嵌套对象(我说的是数百个对象),因此我知道如何递归调用这些对象,并使它们显示在无序列表中。我似乎不知道如何添加onClick函数,当单击该函数时,它将在嵌套对象中显示下一个级别 我将提供一些截图,让您了解我所拥有的以及我正在努力实现的目标。递归部分让我在如何让它工作的问题上绊倒了。有人有想法吗 类菜单扩展了React.Compone

抱歉,如果这是一个愚蠢/明显的问题,我是Javascript/React新手。我正在尝试创建一个菜单,其中包含从API调用中获取的JSON对象。由于JSON数据是一组嵌套对象(我说的是数百个对象),因此我知道如何递归调用这些对象,并使它们显示在无序列表中。我似乎不知道如何添加onClick函数,当单击该函数时,它将在嵌套对象中显示下一个级别

我将提供一些截图,让您了解我所拥有的以及我正在努力实现的目标。递归部分让我在如何让它工作的问题上绊倒了。有人有想法吗

类菜单扩展了React.Component{
状态={
类别:[]
};
makeMenuLayer=图层=>{
const layerKeys=Object.entries(layer.map)([key,value])=>(
    {key} {this.makeMenuLayer(值)}
)); 返回{layerKeys}; }; componentDidMount(){ axios.get(“https://www.ifixit.com/api/2.0/categories)然后(响应=>{ this.setState({categories:response.data}); }); } render(){ const{categories}=this.state; 返回{this.makeMenuLayer(categories)}; } }
这就是当前此代码显示的内容。我试图使它只显示第一层对象,然后当单击每个元素时,显示下一层。例如,如果我单击Apparel,它将显示附件、衣服、眼镜等。如果我单击Apparry,它将显示领带和雨伞

这是我正在处理的数据的屏幕截图,显示在控制台中

有很多方法可以做到这一点,但是一般的想法是跟踪一些额外的状态,以确定菜单层次结构中的哪个层当前可见,哪个不可见

一种快速且相当简单的方法是在组件状态中添加一个名为
hidden
的额外映射,该映射将跟踪菜单树中菜单层的可见性

这样的东西可能适合你:

class Menu extends React.Component {
    state = {
    categories: [],
    /* Add extra state to track which layers are visible or not */
    hidden: {}
    };

    /* Define a local helper function that toggles the layer by key */
    toggleMenuLayer = (key) => {

        /* A state change is required to cause a re-render of the menu */
        this.setState(state => {

            const { hidden } = state
            const isHidden = hidden[ key ];

            /* Add or update hidden state for key in hidden map */
            return { hidden : { ...hidden, key : !isHidden }}
        });
    }

    /* Define a local helper function that determines if a layer is visible by its key */
    isLayerToggled = (key) => {

        /* If "not" hidden then layer is visible, or "toggled" */
        return !this.state.hidden[ key ]
    }

    makeMenuLayer = (parentKey, layer) => {
        const layerKeys = Object.entries(layer).map(([key, value]) => {

            /* Compose a unique key for this item based on it's position in the hierarchy */
            const itemKey = `${parentKey}.${key}`;

            return (
                <ul>
                { /* Add a toggle button for this layer */ }
                <button onClick={() => this.toggleMenuLayer(itemKey)}>{key}</button>

                { /* If layer is toggled then display it's contents */ }
                { this.isLayerToggled(itemKey) && this.makeMenuLayer(value) }
                </ul>
            )
        });
        return <div>{layerKeys}</div>;
    };

    componentDidMount() {
        axios.get("https://www.ifixit.com/api/2.0/categories").then(response => {
            this.setState({ categories: response.data });
        });
    }

    render() {
        const { categories } = this.state;
        return <div>{this.makeMenuLayer(categories)}</div>;
    }
}
类菜单扩展了React.Component{
状态={
类别:[],
/*添加额外状态以跟踪哪些图层可见或不可见*/
隐藏:{}
};
/*定义按键切换图层的局部辅助函数*/
toggleMenuLayer=(键)=>{
/*需要更改状态才能重新呈现菜单*/
this.setState(state=>{
常量{hidden}=状态
const ishiden=隐藏[键];
/*添加或更新隐藏映射中密钥的隐藏状态*/
返回{隐藏:{…隐藏,键:!isHidden}
});
}
/*定义一个局部辅助函数,用于确定图层的关键点是否可见*/
isLayerToggled=(键)=>{
/*如果“未”隐藏,则图层可见,或“切换”*/
return!this.state.hidden[键]
}
makeMenuLayer=(parentKey,层)=>{
const layerKeys=Object.entries(layer.map)([key,value])=>{
/*根据此项在层次结构中的位置为其组合唯一键*/
常量itemKey=`${parentKey}.${key}`;
返回(
    {/*为该层添加切换按钮*/} this.toggleMenuLayer(itemKey)}>{key} {/*如果切换图层,则显示其内容*/} {this.isLayerToggled(itemKey)&&this.makeMenuLayer(value)}
) }); 返回{layerKeys}; }; componentDidMount(){ axios.get(“https://www.ifixit.com/api/2.0/categories)然后(响应=>{ this.setState({categories:response.data}); }); } render(){ const{categories}=this.state; 返回{this.makeMenuLayer(categories)}; } }

希望对代码中的注释有所帮助

可能不是最有效的,但我只是想到了使用状态来隐藏/取消隐藏嵌套对象

试试这个

import React from 'react'

class Menu extends React.Component {
  state = {
    categories: [],
    objectKeys: null,
    tempKeys: []
  }

  makeMenuLayer = layer => {
    const { objectKeys } = this.state
    const layerKeys = Object.entries(layer).map(([key, value]) => (
      <ul key={key}>
        <div onClick={() => this.handleShowMore(key)}>{key}</div>
        {objectKeys[key] && this.makeMenuLayer(value)}
      </ul>
    ))
    return <div>{layerKeys}</div>
  }

  handleShowMore = key => {
    this.setState(prevState => ({
      objectKeys: {
        ...prevState.objectKeys,
        [key]: !this.state.objectKeys[key]
      }
    }))
  }

  initializeTempKeys = layer => {
    Object.entries(layer).map(([key, value]) => {
        const newTempKeys = this.state.tempKeys
        newTempKeys.push(key)
        this.setState({ tempKeys: newTempKeys })
        this.initializeTempKeys(value)
      }
    )
  }

  initializeObjectKeys = () => {
    const { tempKeys } = this.state
    let tempObject = {}

    tempKeys.forEach(tempKey => {
      tempObject[tempKey] = true
    })

    this.setState({ objectKeys: tempObject })
  }

  async componentDidMount () {
    const res = await fetch('https://www.ifixit.com/api/2.0/categories')
    const categories = await res.json()
    this.initializeTempKeys(categories)
    this.initializeObjectKeys()
    this.setState({ categories })
  }

  render () {
    const { categories } = this.state
    return <div>{this.makeMenuLayer(categories)}</div>
  }
}

export default Menu

从“React”导入React
类菜单扩展了React.Component{
状态={
类别:[],
objectKeys:null,
临时钥匙:[]
}
makeMenuLayer=图层=>{
const{objectKeys}=this.state
const layerKeys=Object.entries(layer.map)([key,value])=>(
    this.handleShowMore(key)}>{key} {objectKeys[key]&&this.makeMenuLayer(value)}
)) 返回{layerKeys} } handleShowMore=key=>{ this.setState(prevState=>({ 对象键:{ …prevState.objectKeys, [key]:!this.state.objectKeys[key] } })) } initializeTempKeys=图层=>{ Object.entries(layer.map)([key,value])=>{ const newTempKeys=this.state.tempKeys newTempKeys.push(按键) this.setState({tempKeys:newTempKeys}) 此.initializeTempKeys(值) } ) } initializeObjectKeys=()=>{ const{tempKeys}=this.state 设tempObject={} tempKey.forEach(tempKey=>{ tempObject[tempKey]=真 }) this.setState({objectKeys:tempObject}) } 异步组件didmount(){ const res=等待取数('https://www.ifixit.com/api/2.0/categories') const categories=await res.json() 此选项。初始化MPKEYS(类别) this.initializeObjectKeys() this.setState({categories}) } 渲染(){ const{categories}=this.state 返回{this.makeMenuLayer(categories)} } } 导出默认菜单
Hey Ryan再次感谢您的帮助。我想知道你是否能帮我做这件事。我想在下面有另一层的每个元素旁边添加箭头(基本上,如果这个元素有子元素,则显示一个箭头来指示)。你知道我会在这里这样做吗?你可以为
value
添加一个检查器。如果不是空数组,则返回一些