【问题标题】:How can I change React state from nested dynamically created components?如何从嵌套的动态创建的组件中更改 React 状态?
【发布时间】:2021-07-30 17:56:05
【问题描述】:

我从数据库中提取项目信息,然后根据我有多少项目,我推送到一个数组并渲染。问题是由于某种原因“dropdownOptions”不会在显示和隐藏之间切换。

我基本上只是希望能够单击下拉箭头并让它显示“删除”或“设置”等选项。也不确定我是否需要为每个创建的项目组件创建一个单独的 id。

代码片段:

// Using hook to set display of dropdown to false

const [dropdownOptions, setDropdownOptions] = useState(false);


// This piece automatically renders clickable projects from database

const pList = [];
                    for (var i = 0; i < project_list.length; i += 1) {
                      var projectName = project_list[i]
                      pList.push (
                          <div className="projects" key={i}>
                              <div className="projectName">Name: <div className="projectText">{projectName}</div></div>
                              <div className="projectDate"> Date Created: <div className="projectText">{date}</div></div>
                              <div className="projectLabels">LabelsLeft:</div>  
                              <div className="drop">
                                  <div className="dropArrow" onClick{setDropdownOptions(!dropdownOptions)}>
                                        {dropdownOptions ? <ProjectDropdown/> : null}
                                  </div>
                              </div>
                          </div>
                          );
                    };
                    setpList(pList);
                })


// Then I simply render the component "pList"

        return (
      <div className="container">
        <div className="projectsContainer">
          <div className="projectsTitle">
            Projects:
            <div className="addProject" onClick={toggleShow}></div>
          </div>
          {pList}
          <div className="message">
              {message}
          </div>
        </div>
      </div>
    )

用户在项目上按下 droparrow 之前的理想外观是这样的

然后是这个,但只针对点击的项目

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    您必须选择解决此类问题:

    1- 为列表中的每个项目创建一个状态,对于每个项目,您都有一个 boolean 可以判断该项目是否已打开其下拉列表

    2- 制作单个状态项,但将其设为代表单击项 ID 的数字,当该 ID 与 state 匹配时,您打开该项目的下拉列表

    const [selectedItem, setSelectedItem] = useState(-1);
    

    在你的 jsx 中

    <div className="projects" key={i}>
        <div className="projectName">Name: <div className="projectText">{projectName}</div></div>
        <div className="projectDate"> Date Created: <div className="projectText">{date}</div></div>
        <div className="projectLabels">LabelsLeft:</div>
        <div className="drop">
            <div className="dropArrow" onClick{()=>setSelectedItem(i)}>
                {selectedItem == i ? <ProjectDropdown /> : null}
            </div>
        </div>
    </div>
    

    作为建议,最好添加从您的 API 获取的真实 id,因为传递给每个项目的密钥对于反应非常重要,而不仅仅是显示下拉列表。


    建议的解决方案代码

    function TestSolution() {
    
        // Using hook to set display of dropdown to false
    
        const [selectedItem, setSelectedItem] = useState(-1);
    
    
        // This piece automatically renders clickable projects from database
    
        const pList = project_list.map((projectName, i) => (
            <div className="projects" key={i}>
                <div className="projectName">Name: <div className="projectText">{projectName}</div></div>
                <div className="projectDate"> Date Created: <div className="projectText">{date}</div></div>
                <div className="projectLabels">LabelsLeft:</div>
                <div className="drop">
                    <div className="dropArrow" onClick{() => setSelectedItem(i)}>
                        {selectedItem == i ? <ProjectDropdown /> : null}
                    </div>
                </div>
            </div>
        ))
    
    
    
        // Then I simply render the component "pList"
    
        return (
            <div className="container">
                <div className="projectsContainer">
                    <div className="projectsTitle">
                        Projects:
                        <div className="addProject" onClick={toggleShow}></div>
                    </div>
                    {pList}
                    <div className="message">
                        {message}
                    </div>
                </div>
            </div>
        )
    }
    

    react 中的思维方式不同,如果某些数据可以从另一个状态或数据派生出来,就不要为某些数据使用新状态,这会让你的生活更轻松。

    【讨论】:

    • 选择了选项二,奇怪的是当我在钩子上手动更改 selectedItem 时它可以工作,但是当我点击 droparrow 时它什么也不做,甚至没有注册点击。
    • project_list 是如何传递给你的组件的?
    • const project_list = json.projectList;从 Flask jsonify 收到
    • 好的,如果没有完全重现问题,我无法在脑海中调试该代码,因此我建议清理一些代码并让显示的数据直接来自源数据,而不使用特殊状态它,那会更干净,我会更新答案并添加建议的解决方案
    • 那么我建议总是渲染 dropdown 并传递一个名为 open 的布尔值 prop,它在内部确定它是否会被打开
    猜你喜欢
    • 2020-04-07
    • 2019-02-14
    • 2021-03-01
    • 2023-01-23
    • 2021-08-15
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 2018-05-06
    相关资源
    最近更新 更多