【问题标题】:<select> does not change its selected <option> when setting a default value<select> 在设置默认值时不会更改其选择的 <option>
【发布时间】:2019-02-18 15:24:24
【问题描述】:

我正在通过 props 创建一个具有默认值的选择组件,但是当我突然尝试选择一个选项时,选择什么都不做。

我试图不设置一个初始值来解决问题,但程序不应该那样做。

//UserMaintenanceModal
class UserMaintenanceModal extends Component {
    state = {
        user_department: this.props.data.user_department,
        departments: [
            {id: 1, name: "IT"}, {id:2, name: "BM"}
        ]
    }

    handleChange = (event) => {
        this.setState({user_department: event.target.value});
    }

    render(){
        const { user_department } = this.state;
        return (
            <label>Department</label>
            <select 
                className="form-control form-control-sm" 
                name='user_department'
                value={user_department}
                onChange={this.handleChange}
             >
             {
              this.state.departments != null && this.state.departments.map(
                       department => 
                           <option 
                               key = {department.id} 
                               value = {department.name}
                            >
                                {department.name}
                            </option>
                      )
               }
               </select>
        )
    }
}

解决方案

对不起,我的错。我没有展示所有的源代码。之所以没有更改它,是因为这段代码位于父组件内。

//NavComponent

componentWillMount() {
    document.addEventListener('mousedown', this.handleClick, false);
}

componentWillUnmount() {
  document.removeEventListener('mousedown', this.handleClick, false);
}

我确实从here 获得了此代码。当在组件外部单击时,它会隐藏活动的下拉导航菜单。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    看看我制作的这个 CodePen:https://codepen.io/Gesma94/pen/QYYWKG

    由于你是从 props 中取值,这意味着父 Component 将值保持在状态(可能),所以,当你选择一个选项时,你需要更新父 Component 的状态,并且为了为此,您需要使用父级的选项将 handlerFunction 传递给组件。

    class List extends React.Component {
        options = ["one", "two", "threee"];
    
        render() {
            const {handleChange, value} = this.props;
            return (
                <select value={value} onChange={handleChange}>
                    {
                        this.options.map((option, index) =>
                            <option key={index} value={option}>
                                {option}
                            </option>
                     )}
                </select>
            );
        }
    }
    
    class App extends React.Component {
        constructor(props) {
            super(props);
    
            this.state = {value: "one"};
        }
    
        handleChange = (e) => {
            this.setState({value: e.target.value})
        }
    
      render() {
          return <List handleChange={this.handleChange} value={this.state.value} />
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    

    编辑好的,所以..问题之一是我昨天说的:你将默认值传递给UserMaintenanceModal组件,它保存在App组件的状态中.但是,在 UserMaintenanceModal 组件中,您更新了自身的状态,而不是 App 组件的状态,因此您有点不一致。

    无论如何,这不是您最大的问题:据我所知,存在一些“混乱”(或者更可能是我不完全理解您想要实现的目标:))。所以,现在我假设,正如我在评论中所说,您只想显示属于所选部门的所有用户!

    我看到,在App 组件的handleChange 中,您将有关当前单击用户的信息保存在状态的data 属性中(我不知道这是强制性的还是尝试达到我的假设)。如果您想保存该信息,这是多余的,因为您已经在users 属性中拥有所有这些信息:您可以只保存userId 或点击用户的users 数组中的位置。

    然后,我也不明白为什么 showModal 最初设置为 false 并在您单击用户时变为 true:这样似乎所有用户在开始时都应该可见,一旦您单击其中一个,您有点按被单击用户所属的部门过滤用户。但如果是这种情况,我不知道为什么选择应该在之后变得可见..:S

    最后,在App 组件的render() 方法中,您应该以某种方式说“嘿,只渲染属于所选部门的用户”,这是您没有尝试的(据我所知)。在下面的示例中,我使用了 filter 本机函数,但您可以只保留 map 函数并仅在其 user_department 等于当前选择的值时返回用户。

    无论如何,我还假设选择应该从一开始就可见,并且我已经分叉了你的 codepen,看看这个,如果这是你想要的,请告诉我:https://codepen.io/Gesma94/pen/aXXjvE

    请注意,在此示例中,部门值处于 UserMaintenanceModal 状态,这根本不是一件好事:您应该从保存在 @987654345 状态下的 users 数组中检索部门@ 组件,然后将它们传递给 UserMaintenanceModal 组件。我的意思是,您应该执行类似“好的,让我们看看我所有的用户,看看我拥有的所有部门......现在,我有了它,让我们将它们传递给UserMaintenanceModal

    【讨论】:

    • 由于您的编辑,我制作了第二个 codepen → codepen.io/Gesma94/pen/vbbYzE 老实说,它有效,所以也许其他地方有错误..?顺便说一句,如果您希望 this.props.data.user_department 的值在您更改 UserMaintenanceModal 的状态时也会发生变化,那么它不会发生:您已经在 UserMaintenanceModal 的状态内创建了该值的副本,所以父组件不会改变
    • 我编辑了你的工作和我的反应应用程序的确切代码。它适用于codepen,但不适用于我的项目。检查此 codepen.io/anon/pen/aXXdqz?editors=0011 并尝试在您的计算机上创建一个反应应用程序。
    • 你能解释一下你工作的目的是什么吗?我猜你想只显示列Department 等于select 中选择的值的行。我说的对吗?
    • 您的权利,因为不需要包含其他属性。这是为了演示错误。
    • 我已经在上面编辑了答案。看看吧! :)
    【解决方案2】:

    你可以把默认值 prop 放在组件状态,继续使用。

    示例

    class App extends React.Component {
      state = {
        options: ["foo", "bar", "baz"],
        selectedOption: this.props.defaultOption
      };
    
      onChange = e => {
        this.setState({ selectedOption: e.target.value });
      };
    
      render() {
        const { options, selectedOption } = this.state;
    
        return (
          <select value={selectedOption} onChange={this.onChange}>
            {options.map((option, index) => (
              <option key={index} value={option}>
                {option}
              </option>
            ))}
          </select>
        );
      }
    }
    
    ReactDOM.render(<App defaultOption="bar" />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

    【解决方案3】:
    问题

    就我而言,我想根据selected 字段切换或渲染要填充的不同组件。每当我切换它时,我都无法重置渲染组件的选定字段。结果,我无法首先显示正确的占位符option。这是错误的,可能会使用户感到困惑。

    解决方案

    我在select 标签中添加了defaultValue。 这是我希望用户第一次看到的占位符

    我在select 标签中添加了value。 这有助于我跟踪用户何时改变主意或清理数据。

     <select
            name={inputName}
            id={inputId}
            className="input-controller-required"
            required
            onChange={onHandleInputChange}
            defaultValue={defaultValue}
            value={defaultValue}   // I forgot to add value
          >
            <option disabled value="">{placeholder}</option>
            {
              options.map((item, index) => (
                <option value={item.value} key={index}>{item.text}</option>
              ))
            }
          </select>
    

    感谢@Jolly 的回答和其他贡献者的支持。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-28
      • 2022-08-10
      • 1970-01-01
      • 1970-01-01
      • 2012-02-19
      • 1970-01-01
      相关资源
      最近更新 更多