Связать элементы управления с элементами родственного компонента - PullRequest
0 голосов
/ 11 января 2020

У меня есть массив изображений, и я отображаю их, чтобы показать изображения. Я положил кнопку для их изменения, но я не знаю, как можно разделить их, чтобы изменить правильное изображение. Это работает как изменение только последнего индекса каждого массива галереи. например, если галерея имеет 4 элемента, она только изменит четвертый элемент! Я думаю, может быть, это из-за ссылки одинаковы ... Я использую избыточное спасибо.

class ImagesInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      val: "",
      currentImgPrev: []
    };

    this.inputFileChanged = this.inputFileChanged.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    let input = this.refs.input_reader;
    input.click();
  }

  inputFileChanged(e, index) {
      let file = e.target.files[0],
        reader = new FileReader(),
        self = this;
      reader.onload = function(r) {
        let img = self.state.currentImgPrev;
        const w = r.target.result;
        img[index] = w
        self.setState({
          currentImgPrev: img
        });
      };
      reader.readAsDataURL(file);
      self.setState({ val: reader });
      console.log(self.state.val);
  }

  render() {
    return (
            {this.props.gallery.map((g, index) => (
              <Col xs={4} className="text-center" key={index}>
                <img src={g} alt="landpic" />
                <Button
                  htmlFor={g}
                  onClick={this.handleClick}
                >
                  Change
                </Button>
                <input
                  type="file"
                  id={g}
                  style={{ display: "none" }}
                  ref="input_reader"
                  onChange={e => {
                    this.inputFileChanged(e, index);
                    this.props.handleSubmit(
                      this.state.currentImgPrev[index],
                      index,
                      this.props.name,
                    );
                  }}
                />
              </Col>
            ))}
    );
  }
};

const mapDispatchToProps = dispatch => {
  return {
    handleSubmit: (currentImgPrev, i, frameName) => {
      dispatch({
        type: "ADD_IMAGE",
        addedImg: currentImgPrev,
        indexEl: i,
        frameElName: frameName,
      });
    }
  };
};
export default connect(null, mapDispatchToProps)(ImagesInput);

1 Ответ

1 голос
/ 12 января 2020

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

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

Просто передайте некоторую привязку изображения (например, id или name) в качестве свойства соответствующему элементу управления (кнопка, флажок и т. Д.), Чтобы можно было запускать действия с нужным изображением при необходимом событии .

См. Следующий фрагмент кода в качестве доказательства концепции:

//prerequisites
const { render } = ReactDOM,
      { useState } = React,
      { createStore } = Redux,
      { connect, Provider } = ReactRedux
      
//mocking image src data stored within global state,
//setting up dummy reducer and store
const initialState = {imgData:[{name:'Lion',imgSrc:'https://images.theconversation.com/files/243439/original/file-20181101-83635-1xcrr39.jpg?ixlib=rb-1.1.0&q=45&auto=format&w=926&fit=clip'},{name:'Zebra',imgSrc:'https://img3.akspic.ru/fit/95583-ekosistema-griva-zebra-pastbishhe-zoopark-x750.jpg'},{name:'Monkey',imgSrc:'https://img.jakpost.net/c/2017/09/12/2017_09_12_32421_1505189647._large.jpg'}]},
      appReducer = (state=initialState,action) => state,
      store = createStore(appReducer)

//image ui component
const Image = ({imageSource, status}) => (
  <div class="image"><img src={imageSource} style={{visibility: status}}/></div>
)

//parent component
const ImgGallery = ({images}) => {
  const [imagesStatus, setImagesStatus] = useState(images.reduce((res,{name}) => (res[name] = 'visible', res),{})),
        onToggleStatus = animalName => setImagesStatus({...imagesStatus, [animalName]: imagesStatus[animalName] == 'visible' ? 'hidden' : 'visible'})
  return (
    <div>
      {images.map(({imgSrc, name},key) => <Image imageSource={imgSrc} status={imagesStatus[name]} {...{key}} />)}
      <br />
      {images.map(({name},key) => <label {...{key}}>Hide the {name}<input type="checkbox" value={name} onChange={e => onToggleStatus(e.target.value)} /></label>)}
    </div>
  )
}

//use connect to attach global state imgData to images prop
const mapStateToProps = ({imgData}) => ({images:imgData}),
      ImgGalleryContainer = connect(mapStateToProps)(ImgGallery)
      
//render parent component inside Provider
render (
  <Provider {...{store}}>
    <ImgGalleryContainer />
  </Provider>,
  document.getElementById('root')
)
.image {
  display: inline-block;
  vertical-align: top;
  width: 100px;
  height:70px;
  border: 2px solid darkblue;
  margin-right: 20px;
  padding: 5px;
}

.image img {
  max-width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.3/react-redux.min.js"></script><div id="root"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...