React Props не передает информацию на страницу подтверждения - PullRequest
1 голос
/ 28 апреля 2020

Я новичок в React, и я разрабатываю форму отправки с несколькими полями в React. Он имеет несколько полей ввода Textfield и функцию ввода тегов. Пользователь вводит свою информацию в поля, и в конце информация должна отображаться на странице подтверждения. Теперь отображаются все мои данные, кроме тегов (из ввода тегов). В чем проблема?

Форма (дополнительная информация. 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} не отображаются (даже если они правильно зарегистрированы в консоли) Где моя ошибка?

1 Ответ

1 голос
/ 28 апреля 2020

Ваш компонент AdditionalInfo связывает каждый из своих входов с реквизитом handleChange, который был передан ему родителем. Когда поле обновляется, родитель узнает об этом.

Ваш компонент TagsInput сохраняет список тегов в своем состоянии own (ловушка useState). Он никогда не сообщает родителю о любых изменениях, которые он имеет.

Позже, когда ваш родитель (предположительно, не показан) вызывает ConfirmationPage, он не знает о введенных тегах, но он знает о другой информации, потому что было сказано о них.

Вместо этого отследите список тегов в родительском элементе и передайте текущий список тегов (а также обработчики addTag и removeTag) дочернему элементу.

ОБНОВЛЕНИЕ

Я отредактировал вашу песочницу, чтобы показать рабочий пример. Примечание. Мне пришлось удалить множество ссылок на внешние файлы, чтобы заставить его скомпилироваться, поэтому в будущем вы можете захотеть сократить свой код до того вопроса, который у вас есть, перед публикацией песочницы.

https://codesandbox.io/s/tagger-u8fs5

Некоторые примечания:

  1. До этого не было понятно, как работает ваша файловая структура. Теперь, когда я это вижу, вам не нужно фактически перемещать состояние тегов. Это нормально, чтобы TagsInput отслеживал свое собственное состояние. Но все еще верно, что вам нужно обновить его родителя с этим значением. Для этого я добавил функцию updateParent, которая вызывается всякий раз, когда вы добавляете или удаляете тег.
  2. Функцию handleChange нельзя использовать для тегов, потому что она настроена для просмотра для e.target.value и в этом случае мы отправляем ему массив значений напрямую, а не событие со значением. Я добавил handleChangeRaw функцию, которая позволяет это.
  3. Когда вы обновляете состояние тегов (добавляете / удаляете), я сохраняю новый временный массив в константе, которая затем может также быть отправлено родителю. Вы не хотите просто устанавливать его напрямую (т. Е. С помощью setTags), а затем иметь прямую ссылку на функцию updateParent в этом состоянии, потому что она будет на один рендеринг позади (то есть на один тэг позади)
  4. On на странице сводки я добавил .join(',') к выводу ваших тегов; в противном случае он просто пытается создать строку из элементов, которая будет запускать слова вместе.
  5. Я бы не стал устанавливать значение e.target.value в значение "" для сброса поля ввода. Это немного отстает от меня (вы меняете событие, которое было моментом времени). Вместо этого у меня есть ваш код, использующий вход как «контролируемый» вход, то есть мы отслеживаем его состояние и меняем его всякий раз, когда хотим (например, когда нам нужно сбросить его). Это отдельно от отслеживания списка тегов; здесь мы просто отслеживаем текущее значение поля ввода.

Итак, в итоге, пропущенный шаг действительно заключался в том, что ваш родительский компонент никогда не узнавал об изменениях в тегах. Когда у вас есть вложенные компоненты (родительские / дочерние отношения), вам нужно аккуратно передавать информацию вверх и вниз; они не делятся автоматически тем, что знают.

...