【问题标题】:How to use props or state to render or not render 1 out of these 5 forms on click?如何在点击时使用道具或状态来渲染或不渲染这5种形式中的一种?
【发布时间】:2018-06-23 01:42:57
【问题描述】:

我正在寻找有关如何在 React 中单击五个相关按钮之一来呈现五分之一表单的建议。我已经让它实际上适用于一种形式,但我很确定这不是 React 中应该做的事情。

有一个带有 5 个按钮的侧边栏和一个显示一些内容的内容区域。单击侧栏中的相应按钮后,其中一个表单应出现在内容区域中。一次只能显示一个表单。侧边栏和内容区域都是一个名为 GraphArea 的类中的函数,用于呈现它们。

AddNodes(侧边栏中的五个按钮之一):

const AddNodes = ({ showAdd }) => (
    <li role="presentation" className="list-inline">
        <a href="" className="nav-link" onClick={showAdd}>
            <i className="fa fa-plus" aria-hidden="true"/> Add
        </a>
    </li>
);
export default AddNodes;

问题是,有五个表单和按钮...没有办法合理地继续这样下去。

我正在使用 Apollo 链接状态。默认情况下,所有 5 五个表单都不会呈现,因此它们的默认值为 false。这些值被写入缓存。 Apollo 查询并在点击时将缓存中的默认值更改为 true。

如果你能在这里告诉我正确的方式,那对我来说意义重大。我错过了在 React 中如何工作的“点击”,这将是一个很好的机会。这是侧边栏和内容区域的父完整组件:

GraphArea:(父级)

class GraphArea extends Component {

    render() {

        const { updateEditGraph, editGraph: { mode } } = this.props;

        const showAdd = (e) => {
            updateEditGraph(
                {
                    variables: {
                        index: 'mode',
                        value: 'addNode'
                    }
                });
            e.preventDefault()
        };

        const showLink = (e) => {
            updateEditGraph(
                {
                    variables: {
                        index: 'mode',
                        value: 'addLink'
                    }
                });
            e.preventDefault()
        };

        return (
            <div className="item">
                <GraphSidebar showAdd={showAdd} showLink={showLink}/>
                <GraphContent/>
            </div>
        )
    }
}

export default compose(
    graphql(updateEditGraph, {name: 'updateEditGraph'}),
    graphql(getEditGraph, {
        props: ({data: {editGraph}}) => ({
            editGraph
        })
    })
)(GraphArea);

图表内容:

class GraphContent extends Component {

    render() {

        let content;

        if (this.props.editGraph.mode === 'addNode') {
            content = <AddNodesForm/>
        } else if (this.props.editGraph.mode === 'addLink') {
            content = <LinkNodesForm/>
        } else {
            content = null;
        }

        return (
            <div className="content">
                {content}
                <Graph/>
            </div>
        );
    }
}

export default compose(
    graphql(getEditGraph, {
        props: ({data: {editGraph}}) => ({
            editGraph
        })
    })
)(GraphContent);

GraphSidebar:

const GraphSidebar = ({ showAdd, showLink }) => (
            <div className="avatars">
                <ul>
                    <AddNodes showAdd={showAdd} />
                    <SequenceNodes />
                    <EditNodes />
                    <LinkNodes showLink={showLink} />
                    <DeleteNodes />
                </ul>
            </div>
        );

【问题讨论】:

  • GraphArea 是 1 个表格,而您有 5 个表格,或者 &lt;div className="item" /&gt; 是 1 个表格?
  • &lt;AddNodesForm /&gt; 是表单。它在&lt;div className="content"&gt; div 中。其中有五种形式,但这里的代码中只有一种。我发现atticuswhite.com/blog/… 上的 if else 渲染有很多改进的机会。我猜 if else 逻辑也更适合 switch 语句。我不明白的事情似乎与道具和状态有关。从我读到的,它一定是关于状态的,因为数据可以改变,但我不确定这在代码中是如何表现出来的。

标签: javascript reactjs apollo


【解决方案1】:

我会回答原则上应该发生的事情。

你说你有一个顶级组件GraphArea,它呈现用于选择表单的组件和表单的容器:

<div>
  <GraphSidebar onClickName={handleClick}/>
  <GraphContent/>
</div>

GraphSidebarGraphContent 以这样的方式相关,GraphSidebar 改变了应该在GraphContent 上呈现的状态,即它们与相同的状态相关。因此,他们的共同父母 (GraphArea) 应该保持该状态。然后将状态传递给包含表单的GraphContent

GraphArea 设为class:

class GraphArea extends React.Component {

   constructor(){
    super();
    this.state = {formId: 1};
   }

   handleClick(formId) {
     this.setState({fromId: formId});
   }

   render(){
    return (
    <div>
     <GraphSidebar onClickName={handleClick}/>
     <GraphContent formId={this.state.formId}/>
    </div>  
   ) 
   }
}

另外我认为你说GraphContent 不直接呈现表单,而是呈现呈现表单的其他一些组件。您将formId 作为属性通过嵌套组件一直传递到选择要呈现的表单的组件。例如,如果 GraphContent 呈现 Graph 组件,该组件呈现(选择)您这样做的表单:

<div className="content">
    <Graph formId={this.props.formId}/>
</div>

或者只是

<div className="content">
    <Graph formId={formId}/>
</div>

如果GraphContent 不是一个类,而是一个类似的函数

GraphContent = ({formId}) => {
    ....
}

假设 Graph 最终是呈现(选择)表单的组件,然后您可以使用:

Graph = ({formId}) => {
    if (formId === 1) {
      return(<div>...code for form1</div>)
    } else if (formId === 2) {
      return(<div>...code for form2</div>)
    } ...
}

【讨论】:

  • Croraf,感谢您抽出宝贵时间发布答案,很抱歉我的回复有点晚了。我已经考虑了很多。你的回答给了我一些新的想法,我更新了我的代码。我觉得现在好一点了。如果我继续这样下去,我仍然需要编写 5 个 onClick 函数。我也仍然没有使用状态,我只是将新值传递给商店。 (5 种不同的模式,而不是 5 个真值或假值)所以我想我仍然不完全确定设置状态或从商店获取和发布新值之间的区别。
猜你喜欢
  • 2015-08-09
  • 2022-06-23
  • 2011-10-30
  • 1970-01-01
  • 2021-09-25
  • 2020-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多