React Props无法将信息传递到确认页面。

问题描述 投票:0回答:1

我是React的新手,我正在React中设计一个有多个字段的提交表单。它有一些Textfield输入框和一个Tags输入功能。用户在字段中输入他们的信息,在最后,信息必须显示在一个确认页面上。现在我所有的信息都显示出来了,除了标签(来自标签输入)。问题出在哪里?

表格(AdditionalInfo.js)

export const TagsInput = props => {
  const [Tags, setTags] = React.useState(props.Tags)
  const removeTags = indexToRemove => {
    setTags([...Tags.filter((_, index) => index !== indexToRemove)])
  }
  const addTags = event => {
    if (event.target.value !== '') {
      setTags([...Tags, event.target.value])
      props.selectedTags([...Tags, event.target.value])
      event.target.value = ''
    }
  }
  return (
    <div className='tags-input'>
      <ul id='tags'>
        {Tags.map((Tag, index) => (
          <li key={index} className='tag'>
            <span className='tag-title'>{Tag}</span>
            <span
              className='tag-close-icon'
              onClick={() => removeTags(index)}
            >
                             x
            </span>
          </li>
        ))}
      </ul>
      <input
        type='text'
        onKeyUp={event => event.key === 'Enter' ? addTags(event) : null}
        placeholder='Press enter to add tags'
      />
    </div>
  )
}

export class AdditionalInfo extends Component {
  continue = e => {
    e.preventDefault();
    this.props.nextStep();
  };

  back = e => {
    e.preventDefault();
    this.props.prevStep();
  };

 render() {
    const {values, handleChange} = this.props
    const selectedTags = Tags => {
      console.log(Tags)
    }
    return (
        <Container className='ContainerA'>
          <Row>
           <Col className='ACol'>
         <br />
         <br />
          <div>
          <TagsInput selectedTags={selectedTags} Tags={['Nodejs', 'MongoDB']} onChange={handleChange('Tags')}
           defaultValue={values.Tags} />
          </div>
        <Row>
        <Col xs='6' sm='4'>
        <TextField
        placeholder="Country"
        label="Country"
        onChange={handleChange('Country')}
        defaultValue={values.Country}
        margin="normal"
        fullWidth="true"
        id="outlined-basic" 
        variant="outlined"
        required
      />
....
     <div className='buttons-container' style={{position:'relative',bottom:'20px'}}>
       <button onClick={this.back} className='previous'>قبلی</button> 
        <button form='my-form' type='submit' onClick={this.continue} className='next'>ادامه</button>
    </div>

主表格持有人

//AdditionalInfo.js is used here

class CreateJob extends Component {
  state = {
    step:1,
    Title:'',
    requirements:'',
    Country:'',
    Region:'',
    Zipcode:'',
    Benefits:'',
    Company:'',
    InternalCode:'',
    Details:'',
    Tags:[],
    Address:'',
    Department:'',
    Salary:''
  }

  nextStep =() => {
    const {step} = this.state
    this.setState({
      step: step + 1
    })
  }
  prevStep =() => {
   const {step} = this.state
   this.setState({
     step: step - 1
   })
 }

 handleChange = input => e => {
  this.setState({ [input]: e.target.value });
};


  render () {
    const { step } = this.state
    const {Title,Benefits,Company,InternalCode,Detailss,Tags,Address,Department,Salary,requirements,Country,Region,Zipcode } = this.state;
    const values ={Title,Benefits,Company,InternalCode,Detailss,Tags,Address,Department,Salary,requirements,Country,Region,Zipcode}


    return (
      <div>
........
{(()=>{
          switch (step) {
            case 1:
              return(
                <AdditionalInfo
                  nextStep={this.nextStep}
                  handleChange={this.handleChange}
                  values={values}
                />
              )
.........

而这是确认页

//it uses the main form holder component info too

export class Confirmation extends Component {

  continue = e => {
    e.preventDefault();
    this.props.nextStep();
  };

  back = e => {
    e.preventDefault();
    this.props.prevStep();
  };
  render () {
    const {
      values: {
        Title, Benefits,
        Company, InternalCode, Detailss, Department,Tags, Salary,requirements,Zipcode,
        Country,Region
      }
    } = this.props
    return (
....

        <div className='content'>
          <Container>
            <Row>
              <Col xs='6' sm='4' className='TextContent'>
                <Row className='TextInside'> {Salary} : حقوق پیشنهادی</Row>
                <Row>  زیپ کد : {Zipcode}</Row>
                <Row>  کشور : {Country} </Row>
                ..
              </Col>
              <Col xs='6' sm='4' className='TextContent'>
              ...
                <Row>   تگ ها : {Tags}</Row>

对不起,代码太长了,但我不明白为什么{国家}的信息会被删除。(例如)显示在这个确认页面中,但我的TagsInput {Tags}中的标签却没有显示出来(即使它们正确地登录到Console中)我的错误在哪里?

javascript reactjs react-props confirmation
1个回答
1
投票

您的 AdditionalInfo 组件将其每个输入与 handleChange props,它是由父代传递给它的。当一个字段被更新时,父代就会知道它。

您的 TagsInput 组件将标签列表存储在其 自己 状态(useState钩子)。它从来不会通知父体它的任何变化。

之后,当你的父代(大概是,没有显示)调用了 ConfirmationPage它不知道输入的标签,但它知道其他信息,因为它被告知了这些信息。

相反,跟踪父代的标签列表,并将当前的标签列表(以及 "addTag "和 "removeTag "处理程序)传递给子代。

更新

我已经编辑了你的沙盒,展示了一个工作实例。请注意,我确实不得不删除了很多对外部文件的引用,以使其编译,所以在未来,你可能会想在发布沙盒之前,将你的代码剥离到你的确切问题上。

https:/codesandbox.iostagger-u8fs5

一些说明。

  1. 之前我不清楚你的文件结构是如何工作的。现在我明白了,你其实不需要移动标签的状态。让TagsInput跟踪自己的状态是可以的。但它 仍然为真,你需要用这个值更新它的父代。为了做到这一点,我添加了一个 updateParent 函数,该函数在每次添加或删除标签时都会被调用。
  2. 这个 handleChange 函数不能用于标签,因为你设置了寻找 e.target.value 而在这种情况下,我们是直接向它发送一个值的数组,而不是一个带值的事件。我在这里添加了一个 handleChangeRaw 函数,允许这样做。
  3. 当你更新标签的状态(addremove)时,我将新的临时数组存储在一个常量中,然后就可以 被发送到父体。你不希望直接设置(即用 setTags),然后有 updateParent 函数直接引用该状态,因为它将落后于一个渲染(即落后于一个标签)。
  4. 在你的摘要页面,我添加了一个 .join(',') 到您的标签输出中;否则,它只是试图将元素组成一个字符串,将这些词一起运行。
  5. 我会避免将e.target.value的值设置为"",以重置输入字段。这对我来说有点倒退(你改变的是某个时刻的事件)。相反,我让你的代码将输入作为一个 "受控 "的输入,这意味着我们跟踪它的状态,并在我们想要的时候改变它(如当我们需要重置它时)。这与跟踪标签列表是分开的,这里我们只是跟踪输入框的当前值。

所以总结起来,缺失的一步确实是你的父组件从来没有被意识到标签的变化。当你有嵌套的组件时(父子关系),你需要小心翼翼地上下传递信息,它们不会自动分享自己知道的东西。

© www.soinside.com 2019 - 2024. All rights reserved.